Экспорт из Calc в Writer с доп манипуляциями [решено]

Автор Феликс, 26 марта 2015, 14:09

0 Пользователи и 1 гость просматривают эту тему.

Феликс

И снова здравствуйте.
Предыдущая тема помогла полностью автоматизировать составление ежедневного отчета. В ходе работы составляется несколько отчетов в Calc, и они нас полностью устраивают именно в этом варианте из за удобства редакции.
Но в конце дня девушкам-администраторам надо отправить один из них в центральный филиал, а там требуют именно формат Writer. К несчастью, для некоторых девушек это почти невыполнимая задача(
я нашел подходящий код
Sub CalcCellsFormattedToWriterCells
  sel = thisComponent.getCurrentController.getSelection
  on error goto errExit
  if sel.supportsService("com.sun.star.sheet.SheetCellRange") then
     doc = StarDesktop.loadComponentFromURL("private:factory/swriter","_default",0,Array())
     doc.lockcontrollers
     tbl = getNewWriterTable(doc,sel.getColumns.getCount,sel.getRows.getCount)
     transferCellsContents sel,tbl
     REM if msgbox ("close?",1)=1 then doc.close(false)
  else
     exit sub
  endif
errExit:
  doc.unlockcontrollers
End Sub
Sub transferCellsContents(range,tbl)
  addr = range.getRangeAddress
  addr.EndColumn = addr.EndColumn - addr.StartColumn
  addr.EndRow = addr.EndRow - addr.StartRow
  addr.StartColumn = 0
  addr.StartRow = 0
'   myxray range.getCellByPosition(c,r).getText
'   exit sub
  for r = 0 to addr.EndRow
     for c = 0 to addr.EndColumn
        sheetcell = range.getCellByPosition(c,r)
        sheetcelltext = sheetcell.getText
        cell = tbl.getCellByPosition(c,r)
        cursor = cell.createTextCursor
        celltext = cursor.getEnd
'         print "celltext.implementationname: "& celltext.implementationname
        eLines = sheetcelltext.createEnumeration
        while eLines.hasmoreelements
           para = eLines.nextElement
'            print "para.implementationname: "& para.implementationname
'            celltext.insertTextContent(cursor.getEnd,para,false)
           eRanges = para.createEnumeration
           while eRanges.hasMoreElements
              rg = eRanges.nextElement
'               print "rg.implementationname: "& rg.implementationname
              sType = rg.TextPortionType
'               myxray rg
'               prps = rg.getPropertySetInfo.getProperties()
              if sType = "Text" then
                 celltext.setString(rg.getString)
                 cloneProperties rg,celltext
              elseif sType = "TextField" then
'                  myxray rg
                 cursor.HyperlinkURL = rg.TextField.URL
                 cursor.HyperlinkName = rg.TextField.Representation
                 cursor.HyperlinkTarget = rg.TextField.TargetFrame
                 celltext.setString(rg.getString)
              endif
              cursor.collapseToEnd
'               print "cursor.implementationname: "& cursor.implementationname
              celltext = cursor.getEnd(true)
'               print "celltext.implementationname: "& celltext.implementationname
           wend
           if eLines.hasMoreElements then
              cell.insertControlCharacter(cursor,com.sun.star.text.ControlCharacter.LINE_BREAK,False)
              cursor.collapseToEnd
              celltext = cursor.getEnd(true)
           endif
        wend
     next
  next
End Sub
function getNewWriterTable(doc,cols, rows)
  tbl = doc.createInstance("com.sun.star.text.TextTable")
  tbl.initialize(rows,cols)
  xrange = doc.getText
  xrange.insertTextContent(xrange,tbl,true)
  getNewWriterTable = tbl
end function
REM (C) Stephan Wunderlich
REM Archived-At: <http://permalink.gmane.org/gmane.comp.openoffice.devel.api/14674>
function cloneProperties(original, clone)
On Error resume next
properties = original.getPropertySetInfo.getProperties
for i=0 to UBound(properties)
   aName = properties(i).Name
   aValue = original.getPropertyValue(aName)
   if (NOT isNull(aValue)) AND (NOT isEmpty(aValue)) then
       clone.setPropertyValue(aName,aValue)
   endif
next
end function

он копирует выделенную область, создает документ, создает в нем таблицу, и заполняет её.
Но мне надо, что бы он копировал не выделенный диапазон, а конкретный (A1:G61)
Кроме этого надо, что бы он создал документ Writer в формате альбомного листа
Потом написал 3 строчки текста (да еще и прописывал текущую дату):
"Отчет психиатра нарколога
дата: (текущая дата)
Филиал: Кронштадтская"
Потом вставил таблицу.
А в конце сохранял этот файл с указанием текущей даты (отчет за (текущая дата)) в нужную папку.

Я, поняв что программист из меня никакой, воспользовался функцией "записать макрос" и получил таким образом пачку кодов. Но увы, сделать с ними ничего не могу. не понимаю в какое место первого кода это имплантировать, документ в альбомный не переворачивается (открывается окно свойств листа, выбирается альбомный, а потом макрос ждет когда я нажму кнопу ОК), как вставить текущую дату нашел в учебнике но применить не получается, а вместо кириллического названия адреса (рабочий стол\комиссии) он пишет абракадабру (похожую на 16теричный код)

Помогите пожалуйста сотворить такое чудо, если я конечно не слишком многого прошу)

rami

Цитата: Феликс от 26 марта 2015, 12:09Помогите пожалуйста сотворить такое чудо, если я конечно не слишком многого прошу)
У нас во дворе по такому случаю говорили: "Проси больше, всё равно не получишь" ;D

Я предлагаю свести решение к минимальным трудозатратам и телодвижениям. Для этого вы должны дать мне окончательный образец отчёта в формате .odt  (со всеми постоянными текстами и форматами), а также указать какие места должны быть заполнены переменными данными.

Феликс

#2
Извиняюсь, что вчера не ответил, был короткий рабочий день, а на моём компе стоит ms офис.
приложенный ods - это таблица, которая образуется к концу рабочего дня (до 50ти человек + 10 строк на всякий случай). Из нее копируется диапазон A1:G61
Документ odt - это то, что мы должны отправить по почте. В ней постоянны первые 3 строчки, кроме даты. Дата соответственно должна вписываться текущая.
После этих 3х строк вставляется таблица. В принципе шапку таблицы и порядковые номера тоже можно сделать постоянной только тогда копировать надо диапазон B2:G61. Шапка у таблиц одинаковая а меняется только фио, адрес, дата рождения и врач. так что - как удобнее.
Сохраняться этот документ должен именно с таким названием, только должна меняться дата (на текущую конечно). Адрес сохранения - C:\User\Ресепшн_2\Desktop\Комиссии
Было бы вообще фантастикой, если бы после этого ods сохранялся по адресу C:\xsw\arh с именем "псхиатр (текущая дата)".
Если от этого будет проще, файл психиатр.ods всегда лежит на рабочем столе C:\User\Ресепшн_2\Desktop    (утром на рабочий стол автоматически копируется заготовка (пустая таблица с шапкой и порядковыми номерами), по мере работы заполняется, а вечером кидается в архив C:\xsw\arh, а с рабочего стола стирается)
Если надо что бы был готовый шаблонный odt под заполнение, то лучше ему лежать в C:\xsw\

rami

Это первая примерка. Для начала разберёмся с адресами. Определите место для документа отчет психиатра крон 24.03.2015A.odt, сначала он будет простым текстовым документом, а затем превратим его в шаблон. Обратите внимание, дата выше таблицы — это поле с датой создания файла (потом уточним). Откройте психиатр1.ods и в макросе напишите адрес отчёта, выполните макрос, отчёт не открывайте (если он открыт, то закройте перед выполнением макроса) его откроет макрос. Ещё раз проверьте все тексты и форматы, может что-нибудь изменить или приукрасить (макрос ничего не изменяет, только вставляет данные). Потом обсудим, как сделать всё за минимум телодвижений.

Феликс

Ух ты как всё лаконично) Копирует как надо. Единственное,в ячейке где пишется "противопоказаний не выявлено" он делает сначала пустую строку. то есть, как если печатать текст в ручную, он сначала нажимает энтер, а потом вставляет. Получается в ячейке 3 строчки вместо двух (первая пустая).

rami

Цитата: Феликс от 27 марта 2015, 13:26Копирует как надо. Единственное,в ячейке где пишется "противопоказаний не выявлено" он делает сначала пустую строку. то есть, как если печатать текст в ручную, он сначала нажимает энтер, а потом вставляет. Получается в ячейке 3 строчки вместо двух (первая пустая).
Значит в источнике данных (эл.таблице) тоже есть "энтер" и исправлять нужно его, а не результат.
Я раньше писал об этом:
Цитата: rami от 27 марта 2015, 11:51Ещё раз проверьте все тексты и форматы, может что-нибудь изменить или приукрасить (макрос ничего не изменяет, только вставляет данные)
Вы должны очень внимательно проверить всё содержимое обоих документов, иначе то, что макрос делает за десятые доли секунды вы будете исправлять десятки минут.
Сочетание шаблонов с макросами может свести всю работу к нажатию нескольких кнопок.
Я недаром упомянул о "первой примерке" , я ведь не знаю всех подробностей что нужно получить в итоге. Сейчас можно "допилить" название получаемого документа, если хотите.

Феликс

#6
Да, точно. Мой автозаполнятель ставит ентер. исправил - всё работает, отчет получается как надо, кроме текущей даты (но вы говорили это потом уточним). дата должна быть той, когда запущен макрос. То, что в формулах называется (=TODAY). та же TODAY должна прицепливаться к названию документа при его "сохранении как" по другoму адресу.

rami

Цитата: Феликс от 27 марта 2015, 15:40TDATA должна прицепливаться к названию документа при его "сохранении как" по другму адресу.
Какой должен быть типовой заголовок?
1. Отчет психиатра 27.03.2015.odt
2. Отчет психиатра за 27.03.2015.odt
3. другой?
Заголовок будет создаваться в момент создания документа автоматически, но его можно переименовать вручную(если вдруг понадобиться) при первом сохранении или когда нужно (проще всего в файловом менеджере)

На счёт "сохранить как" если использовать шаблон, то можно просто "сохранить" , если простой документ, то нужно "сохранить как" . Я думаю, что лучше использовать шаблон, потому, что он "неубиваемый" , а простой документ девочки в истерике могут превратить в "шедевр кружевного искусства"

Феликс

Цитата: rami от 27 марта 2015, 16:30а простой документ девочки в истерике могут превратить в "шедевр кружевного искусства"
О да))) Именно это сейчас и происходит))))
Заголовок должен быть "отчет психиатра крон 27.03.2015.odt" Но я думаю, это я смогу подправить если что. Я в любом случае этот макрос буду приспосабливать и под другие отчеты. и выполнять эти макросы будет автокликер по таймеру. А то девочки в истерике..... да еще и когда все мысли о побеге домой... это будут даже не кружева))

rami

Замените макрос Main из моего предыдущего документа психиатр1.ods на:
Sub Main
Dim args(0) As New com.sun.star.beans.PropertyValue
args(0).Name = "MacroExecutionMode"
args(0).Value = com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN
oData=ThisComponent.Sheets(0).getCellRangeByName("A2:G61").DataArray
sURL= "Aдрес документа (Отчет психиатра крон.ott) который нужно заполнить(включая расширение)"
oDoc=StarDesktop.loadComponentFromURL(sURL,"_blank",0,args())
oDoc.TextTables(1).DataArray=oData
End Sub

Феликс

#10
В ходе испытаний обнаружена странность.
Я вчера пытался разобраться в чем дело - не разобрался.
Всё переносит, текущую дату ставит, но вот с датами рождения что то странное.
Он правильно переносит дату рождения только в 1,2,4 и 5й строчке. в остальных он ставит числовой формат даты (вместо 20,01,87 пишет 31797). При этом формат ячеек везде одинаковый. Все строки на мой взгляд одинаковые, ни каких отличий я в них не нашел.

update
в принципе, если в шаблоне исходной таблицы "психиатр.ods" выставить формат ячеек "текст", то всё работает как надо.
Пользуясь функцией "записать макрос" дополнил код
Sub exp
Dim args(0) As New com.sun.star.beans.PropertyValue
args(0).Name = "MacroExecutionMode"
args(0).Value = com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN
oData=ThisComponent.Sheets(0).getCellRangeByName("A2:G61").DataArray
sURL= "file:///C:/xsw/is/Отчет психиатра крон.ott"
oDoc=StarDesktop.loadComponentFromURL(sURL,"_blank",0,args())
oDoc.TextTables(1).DataArray=oData
REM сохранение
dim document   as object
dim dispatcher as object
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name = "URL"
args1(0).Value = "file:///C:/Users/%D0%A0%D0%B5%D1%81%D0%B5%D0%BF%D1%88%D0%BD_2/Desktop/%D0%BA%D0%BE%D0%BC%D0%B8%D1%81%D1%81%D0%B8%D0%B8/%D0%BE%D1%82%D1%87%D0%B5%D1%82%20%D0%BF%D1%81%D0%B8%D1%85%D0%B8%D0%B0%D1%82%D1%80%D0%B0%20%D0%BA%D1%80%D0%BE%D0%BD%2029.03.2015.odt"
args1(1).Name = "FilterName"
args1(1).Value = "writer8"

dispatcher.executeDispatch(document, ".uno:SaveAs", "", 0, args1())
End Sub

и теперь осталось выяснить как сделать так, что бы название документа оканчивалось на текущую дату а не на 29.03.2015

rami

Цитата: Феликс от 29 марта 2015, 09:56Пользуясь функцией "записать макрос" дополнил код
Если я скажу вам как это называется, то администраторы форума запишут меня самого в файл "Отчет психиатра крон.ott"
Поясню:
Изначально у вас открыт один документ "психиатр.ods" , который является текущим ("ThisComponent") и остаётся текущим после создания нового документа, таким образом вы пытаетесь "сохранить как" не новый текстовый документ, а старый из которого действует макрос. У вас должна выскакивать ошибка.
Цитата: Феликс от 29 марта 2015, 09:56и теперь осталось выяснить как сделать так, что бы название документа оканчивалось на текущую дату а не на 29.03.2015
А какая дата текущая? День Всемирного Потопа? Сегодня 29.03.2015
Макрос тупо пишет дату на момент создания файла, если отчёт нужно было писать вчера, а вы написали сегодня, то и дата будет сегодняшняя, а не вчерашняя. Если вы не можете создавать отчёт в тот день когда надо, то лучше отказаться от автоматической записи даты и ограничиться только именем файла.

Феликс

Я конечно осознаю как это называется, но если мне не удается понять ооо с учебника, надо заходить с тыла и изучать его путем препарирования)
Ошибки он кстати не выдает. возможно потому, что я вынес его из макросов документа (психиатр1.ods) в общие макросы. перед 2м обращением к ThisComponent идет переопределение документа, а в этот момент активен как раз текстовый документ. Мне так кажется, хотя подозреваю что я сейчас несу чушь)
Сегодня то да - текущая совпадает с 29.03. но мой кривой довесок и завтра сохранит как 29.03. Ваш макрос создает название файла как надо, но мой довесок указывая куда сохранять перебивает и название документа.
Короче, я понял, я сделал грабли вместо макроса) Забудьте пожалуйста моё предыдущее сообщение)
В вашем макросе мне не хватает последнего звена, что бы финальный отчет сохранился в заданной папке. Это возможно как то сделать?

rami

#13
Цитата: Феликс от 29 марта 2015, 16:52Ошибки он кстати не выдает. возможно потому, что я вынес его из макросов документа (психиатр1.ods) в общие макросы.
В этом случае вы правы, а я запустил из документа :( можете заносить меня первым номером в отчёт
Тогда сделаем два изменения:
1. замените предыдущий шаблон "Отчет психиатра крон.ott" на новый (выложил ниже)
2. ваш макрос остаётся, я дописал текущую дату(думаю, что пути к папке не перепутал)
Sub exp   Dim oData, sURL, oDoc
Dim args(0) As New com.sun.star.beans.PropertyValue
args(0).Name = "MacroExecutionMode"
args(0).Value = com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN
oData=ThisComponent.Sheets(0).getCellRangeByName("A2:G61").DataArray
sURL= "file:///C:/xsw/is/Отчет психиатра крон.ott"
oDoc=StarDesktop.loadComponentFromURL(sURL,"_blank",0,args())
oDoc.TextTables(1).DataArray=oData
REM сохранение
dim document   as object
dim dispatcher as object
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name="URL"
args1(0).Value="file:///C:/Users/Ресепшн_2/Desktop/комиссии/Отчет психиатра крон " & Date() & ".odt"
args1(1).Name="FilterName"
args1(1).Value="writer8"
dispatcher.executeDispatch(document, ".uno:SaveAs", "", 0, args1())
End Sub

Феликс

А, так эту шестнадцатиричную кодировку кириллицы в адресе можно смело заменять нормальными буквами? Слава богу) Завтра испытаю)