Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

6 Март 2021, 16:26 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Вы можете задать вопрос по LibreOffice или Apache OpenOffice без регистрации, используя форму
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: Сквозная нумерация документов  (Прочитано 7421 раз)
0 Пользователей и 1 Гость смотрят эту тему.
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Стартовое сообщение: 28 Март 2013, 16:55 »

Slava Polonsky задал на странице сообщества интересный вопрос.
Речь опять идёт о сквозной нумерации создаваемых документов.
Надеюсь, он вот-вот присоединиться к нашей компании и ответит на несколько уточняющих вопросов
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #1: 28 Март 2013, 17:28 »

В общем, заготовка макроса пока выглядит так:
Код:
Sub OnNewWorkbook(oEvent)
Const dictTable="C:\NumDocs\NumbersOfDocuments.ods"
Dim tmpltName$ ' Имя шаблона текущего (только что созданного) документа
Dim targetPath$ ' Где сохранить
Dim targetName$ ' С каким именем
Dim oDoc, tDoc ' Текущий документ и книга-справочник, которая лежит в dictTable
Dim bDisposable As Boolean ' Признак того, что словарь уже был открыт
Dim aTmplts ' Таблица всех нумеруемых шаблонов с первого листа книги tDoc
Dim oSheets, oSheet, oRange, oCell ' Коллекция листов книги, один лист, диапазон ячеек, одна ячейка
Dim i&, j&, num& ' Просто переменные для организации циклов или временного хранения каких-то значений
Dim argOpenFile(0) as new com.sun.star.beans.PropertyValue ' Параметры открытия справочника: скрытый
argOpenFile(0).Name = "Hidden"
argOpenFile(0).Value = True

 print oEvent.EventName+" "+ oEvent.Source.Identifier+" "+ oEvent.Source.DocumentProperties.TemplateName
REM Обрабатываются только электронные книги - другие типы документов пока пропускаем
If oEvent.Source.Identifier <> "com.sun.star.sheet.SpreadsheetDocument" Then Exit Sub
If NOT FileExists(dictTable) Then
MsgBox("Где-то потерялся файл '"+dictTable+"'!", 48, "Ой, беда!")
Exit Sub
EndIf
REM Имя шаблона, на основании которого создан новый документ:
tmpltName = oEvent.Source.DocumentProperties.TemplateName
REM Несколько процедур уже написаны и лежат в стандартной библиотеке Tools
REM Загрузим её:
GlobalScope.BasicLibraries.LoadLibrary("Tools")
  tDoc = OpenDocument(ConvertToURL(dictTable), argOpenFile(), bDisposable)
If IsNull(tDoc) or IsEmpty(tDoc) Then
MsgBox("Не удалось открыть файл '"+dictTable+"' - возможно он кем-то занят", 48, "Упс!")
Exit Sub
EndIf
oSheets = tDoc.getSheets()
oSheet = oSheets.getByIndex(0) ' В словаре нас интересует только первая страница
oRange = oSheet.getCellRangeByPosition(0, 0, 6, GetLastUsedRow(oSheet)) ' С А1 по колонку G до последней заполненной строки
aTmplts = oRange.getDataArray()
j = -1
For i = LBound(aTmplts) To UBound(aTmplts)
If aTmplts(i)(0) = tmpltName Then
j = i
targetPath = aTmplts(i)(1)
targetName = aTmplts(i)(2)
Exit For
EndIf
Next i
if j = -1 Then Exit Sub ' Шаблон этой книги нумерации не подлежит
... ну, и так далее
End Sub
Нужно уточнить относится ли вся эта история только к книгам Calc. Или другие документы (текстовые, например) тоже должны попасть в эту схему?
(Сейчас, к сожалению, должен не надолго отвлечься...)
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #2: 28 Март 2013, 18:59 »

Ну, в общем, что-то в этом роде.

Содержимое архива NumberDocs.zip импортируем в Мои макросы.
Архив NumDocs.zip распаковываем в корень диска C: (там папка с образцом словаря)
На событие офиса цепляем макрос...
Создаем шаблоны, сохраняем их. Вносим нужные строки в словарь...

PS. Ах да! Образец шаблона забыл приложить...

[вложение удалено Администратором]
« Последнее редактирование: 28 Март 2013, 19:04 от JohnSUN » Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #3: 29 Март 2013, 13:21 »

"Продолжаем разговор..." (с) Карлсон
Разумеется, последняя исправленная ошибка в коде оказалась - как всегда! - только предпоследней... Перечитал код свежими глазами и отловил несколько недочетов и помарок: использование индекса i вместо j, неправильная последовательность обработки ошибки записи нового файла и еще кое-чего по мелочи... В общем, код похожий на альфа-версию выглядит так:
Код:
Option Explicit
Option Base 0   

Sub OnNewWorkbook(oEvent)
Const dictTable="C:\NumDocs\NumbersOfDocuments.ods"
Dim tmpltName$ ' Имя шаблона текущего (только что созданного) документа
Dim targetPath$ ' Где сохранить
Dim targetName$ ' С каким именем
Dim oDoc, tDoc ' Текущий документ и книга-справочник, которая лежит в dictTable
Dim bDisposable As Boolean ' Признак того, что справочник уже был открыт
Dim aTmplts ' Таблица всех нумеруемых шаблонов с первого листа книги tDoc
Dim tSheets, oSheets ' Коллекции листов книги-справочника и новой книги
Dim tSheet, oSheet ' Oдин лист со справочником и лист, куда будем вписывать новый номер
Dim tRange ' Диапазон ячеек, с содержимым справочника
Dim tCell, oCell ' Ячейка в справочнике (если нужно ткнуть в ошибку в данных) и ячейка, куда будем вписывать новый номер
Dim i&, j&, num& ' Просто переменные для организации циклов или временного хранения каких-то значений
Dim argOpenFile(0) as new com.sun.star.beans.PropertyValue ' Параметры открытия справочника: скрытый
argOpenFile(0).Name = "Hidden"
argOpenFile(0).Value = True
oDoc = ThisComponent ' Это просто - кто вызвал макрос, тот и есть новый документ
REM Обрабатываются только электронные книги - другие типы документов пока пропускаем
If oEvent.Source.Identifier <> "com.sun.star.sheet.SpreadsheetDocument" Then Exit Sub
If NOT FileExists(dictTable) Then
MsgBox("Где-то потерялся файл '"+dictTable+"'!", 48, "Ой, беда!")
Exit Sub
EndIf
REM Имя шаблона, на основании которого создан новый документ:
tmpltName = oEvent.Source.DocumentProperties.TemplateName
REM Несколько процедур уже написаны и лежат в стандартной библиотеке Tools. Загрузим её:
GlobalScope.BasicLibraries.LoadLibrary("Tools")
REM Загрузим книгу-справочник
  tDoc = OpenDocument(ConvertToURL(dictTable), argOpenFile(), bDisposable)
If IsNull(tDoc) or IsEmpty(tDoc) Then
MsgBox("Не удалось открыть файл '"+dictTable+"' - возможно он кем-то занят", 48, "Упс!")
Exit Sub
EndIf
tSheets = tDoc.getSheets()
tSheet = tSheets.getByIndex(0) ' В справочнике нас интересует только первая страница
REM А на ней данные с А1 по колонку G до последней заполненной строки
tRange = tSheet.getCellRangeByPosition(0, 0, 6, GetLastUsedRow(tSheet))
aTmplts = tRange.getDataArray()
j = -1
REM Перебираем список со второй строки (в первой у нас заголовки, не нужны)
REM в надежде, что имя текущего шаблона в справочнике есть
For i = LBound(aTmplts)+1 To UBound(aTmplts)
If aTmplts(i)(0) = tmpltName Then ' Сравниваем с точностью до регистра символов.
j = i
Exit For
EndIf
Next i
If j = -1 Then ' Шаблон этой книги нумерации не подлежит, его нет в справочнике
If bDisposable Then DisposeDocument(tDoc)
Exit Sub
EndIf
targetPath = aTmplts(j)(1)
targetName = aTmplts(j)(2)
oSheets = oDoc.getSheets()
If (oSheets.getCount()-1 < aTmplts(j)(3)) OR (aTmplts(j)(3)<0) Then
MsgBox("В шаблоне этой книги нет листа с номером "+(aTmplts(j)(3))+" - исправь справочник", 48, "Чиво?!!")
tCell = oSheet.getCellByPosition(3, j)
tDoc.getCurrentController().select(tCell)
tDoc.getCurrentController().getFrame().getContainerWindow().setVisible(True)
DisposeDocument(oDoc) ' Поскольку присвоить номер этому документу не можем, то и не сохраняем его
Exit Sub
EndIf
num = aTmplts(j)(6)+1 ' Увеличили старый номер на единичку
oSheet = oSheets.getByIndex(aTmplts(j)(3))
oCell = oSheet.getCellByPosition(aTmplts(j)(5), aTmplts(j)(4))
oCell.setValue(num) ' Новый номер вписан на свое место. Попробуем сохранить документ
If InStr(targetName, "#") > 0 Then ' Будем позицию номера в имени файла обозначать "решеткой"
targetName = Join(Split(targetName, "#"), Trim(Str(num)))
Else ' В шаблоне имени не предусмотрено место для номера. Будет "номер"_"имя документа"
targetName = Trim(Str(num)) + "_" + targetName
EndIf
If Right(targetPath,1) <> GetPathSeparator() Then targetPath = targetPath + GetPathSeparator()
On Error GoTo NoWriteFile
oDoc.StoreAsURL(ConvertToURL(targetPath+targetName), Array()) ' Возможно вместо Array() потребуется массив каких-то параметров
GoTo NormalContinue
NoWriteFile:
DisposeDocument(oDoc)
MsgBox("Не удалось сохранить документ '"+targetPath+targetName+"' - устрани причину ошибки и попробуй еще раз", 48, "Блин!!!")
GoTo EndOfWork
NormalContinue:
REM Если при сохранении не возникло ошибки, можем перезаписать справочник
On Error GoTo 0
aTmplts(j)(6) = num
tRange.setDataArray(aTmplts)
tDoc.store()
EndOfWork:
If bDisposable Then tDoc.close(True)
End Sub
Если не спешить с созданием очередного файла - работает вроде бы устойчиво... Если успеть создать несколько документов из одного шаблона (восемь раз кликнуть на .ots, например) - заткнется на ошибке...
Коллеги, тут одна проблемка нарисовалась. У Polonsky какой-то из Линуксов, а я в константу dictTable Виндовый путь прописал. Поможете ему исправить эту строчку и пути в файле NumbersOfDocuments (у меня в тех осях навыков маловато)?
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
...
Участник
**
Offline Offline

Сообщений: 23


« Ответ #4: 30 Март 2013, 19:20 »

Цитата:
"Архив NumDocs.zip распаковываем в корень диска C: (там папка с образцом словаря)"

Его же можно куда угодно распаковать. В Linux для простоты можно распаковать в домашний каталог пользователя. Путь там будет выглядеть так: "/home/Имя_Пользователя/NumbersOfDocuments.ods", где "Имя_Пользователя" - имя учетной записи. У меня она зовется dmitry и, следовательно, путь выглядит "/home/dmitry/NumbersOfDocuments.ods".

Внимание! В Unix в путях слешы  в другую сторону повернуты, не "\", а "/".
« Последнее редактирование: 30 Март 2013, 19:21 от deemonizer » Записан
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #5: 30 Март 2013, 21:36 »

Спасибо за помощь, дружище... А /root/... дописывать не нужно? Типа, системе и так ясно, о каком home идет речь?

А насчет "куда распаковывать" - это для тех, кто код читать-править не стал бы... Я-то путь к словарю наглухо вписал...
« Последнее редактирование: 30 Март 2013, 21:38 от JohnSUN » Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
VlhOwn
Форумчанин
***
Offline Offline

Пол: Мужской
Расположение: Ростов-на-Дону
Сообщений: 1 076


« Ответ #6: 30 Март 2013, 21:56 »

/root и /home - разные разделы HDD
Записан
...
Участник
**
Offline Offline

Сообщений: 23


« Ответ #7: 30 Март 2013, 23:47 »

/root - это если сидят из аккаунта root, что является дурным тоном и обычно не принято. Поэтому точно /home. А home там одна, а в ней учетные записи всех пользователей. Там иначе чем в виндовс все устроено, нету лишних повторений.
« Последнее редактирование: 31 Март 2013, 11:32 от deemonizer » Записан
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 764


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #8: 2 Апрель 2013, 10:29 »

Спасибо за разъяснения, коллеги. Чую, нужно выделить время и поковыряться в какой-нибудь Убунте, освежить навыки.

Насчет "не спешить с созданием очередного файла", о котором писал раньше. Кажется, понял причину взглюкивания макроса.
Как выглядит процесс параллельного создания документов:
Первый документ|Второй документ
По шаблону создался новый документ, сработало событие OnNew|
Макрос поискал книгу-справочник среди уже открытых - не нашел|
Открыли справочник с диска, запомнили, что её потом нужно закрыть|Запускаем создание еще одного документа, сработало событие OnNew
Присваиваем номер новому документу, фиксируем номер в справочнике|Поискали справочник среди уже открытых и нашли
Сохраняем новый документ в указанное место с нужным именем|Запомнили, что закрывать справочник не нужно (он ведь был открыт)
Сохраняем справочник|Считываем из справочника данные, присваиваем новый номер документу
Закрываем справочник (ведь запомнили, что нужно закрыть)|Сохраняем документ
|Пытаемся сохранить в справочнике новый номер - а справочника уже нет
Вижу как минимум три варианта обхода ошибки:
1. Никогда не закрывать справочник. Не аккуратненько как-то...
2. Взводить какой-то глобальный логический флаг при запуске макроса. При входе в макрос в цикле ждать пока не завершится обработка предыдущего OnNew и флаг не сбросится, затем взвести флаг, выполнить все нужные действия и флаг сбросить. Тогда вместо параллельного выполнения макросов получим последовательную обработку... Должно сработать. Но что-то грызут сомнения насчет глобальных переменных. Воде как не всегда они себя ведут так, как ожидалось...
3. Отключать обработку события OnNew на время работы макроса. Тоже как-то не по фен-шуй...
Ну, или смириться и просто ждать некоторое время перед созданием очередного документа. Типа, документированная особенность алгоритма Подмигивающий

Ваше мнение? Какой из способов наиболее приемлем? И все ли способы я перечислил?
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!