Вопросы по Writer

Автор geopos, 14 мая 2015, 13:47

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

geopos

Решил создать общую тему для решения задач программирования для Writer. Вопросов будет много, пока пару из них.

Задача: По закладке нужно найти таблицу (ячейку) и естественно заодно проверить находится ли закладка в таблице (аналог Ворда: InRange()).

Вот что у меня получилось на Делфи:

...
const BMarkName = 'CatalogXY';
var BMarks, Table: OleVariant;
     I:          Integer;
begin
  BMarks := Doc.getBookMarks; // Это коллекция закладок
  if not VarIsClear(BMarks) and (not VArIsNull(BMarks)) then
      for I := 0 to BMarks.Count -1 do  // Здесь перебираем по всем закладкам
        if CompareText(BMarks.getByIndex(I).getName, BMarkName) = 0 then // и если нашли нужную: BMarks.getByIndex(I).getName =  BMarkName,
        begin
          ooCursor :=  BMarks.getByIndex(I).getAnchor.getText.CreateTextCursor; // тогда берем курсор
          // <<<<--------- Вот здесь нужно определить Table по закладке?
        end;
end;

geopos

отвечу сам себе - книжка Питоньяка листинг 7.2

geopos

Подскажите, как из ячейки таблицы получить номер строки и колонки?

JohnSUN

Ну, oCell.CellName получить можешь? А потом вызываешь какую-нибудь дикость вроде такой:
procedure getRowColFromCellName(cellName: string; var colName, rowName: string;   var nRow: Integer);
var i           : Integer;
  ch            : string;
begin
  colName := Copy(cellName, 1, Length(cellName));
  rowName := '';
  nRow := -1;
  for i := 1 to Length(cellName) do
    begin
      ch := Copy(cellName, i, 1);
      if (ch >= '0') and (ch <= '9') then
        begin
          colName := Copy(cellName, 1, i - 1);
          rowName := Copy(cellName, i, Length(cellName));
          if TryStrToInt(rowName, nRow) then
            Dec(nRow)
          else
            nRow := -1;
          Exit
        end;
    end;
end;
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

geopos

Ого! Спасибо! Было бы достаточно ответить: oCell.CellName

geopos

Нужно скопировать таблицу и вставить ее ниже скопированной.
         
ooCursor := Table.getAnchor.getText.CreateTextCursor;
ooCursor.gotoEnd(false);  // это не совсем подходит, нужно чтобы сразу за таблицей, а не конец документа
Doc.GetText.insertControlCharacter(ooCursor, 0, false ); //PARA_BREAK
Doc.getText.insertTextContent(ooCursor, Table, false); //  <<<----Здесь ошибка: пишет что уже таблица приатачена

JohnSUN

Цитата: geopos от 15 мая 2015, 16:40
Нужно скопировать таблицу и вставить ее ниже скопированной.
Именно создать копию таблицы впритык к ней же? Но отдельную новую таблицу? Просто размножить строки не пойдёт?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

geopos

Создать копии таблиц не впритык к друг другу, а разделенные пустой строкой. Исходная таблица находится внутри текста.

JohnSUN

Питоньяк в AndrewMacro, когда речь зашла о ViewCursor'е (прочувствовал? не .CreateTextCursor, а .getViewCursor) предлагает
ЦитироватьThe view cursor acts like a table cursor when it is placed inside of a text table, and can therefore be used to copy a text table or a range of cells to a new text table (see my book OpenOffice.org Macros Explained pages 309 – 311).
(это в  8.4. Table cursors and cell ranges)
Но в OOME_3_0.odt на страницах 309 – 311 ничего такого нет. Сейчас оно расположено дальше и называется Listing 380. Copy a text table using the clipboard и Listing 381. Copy a text table using transferable content.
Но прежде чем полезешь разбираться с тем кодом, расскажи над чем ты вообще мучаешься? Есть у меня такое подозрение, что ты уже пошёл не в ту сторону...
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

geopos

Спасибо за ссылки, будем смотреть.
Рассказать так просто не получится... прога специфическая по землеустройству - выдача отчетов из ХМЛ файлов, но не в этом суть.
Будет шаблон с координатами участков и в зависимости от количества этих самых участков будет сгенерировано столько же таблиц в одном документе. Естественно количество участков буду знать только в ран-тайме. В отчете по аналогии с ФастРепортсом будет Общий заголовок и снизу штамп исполнителя, а между ними каталоги координат (таблицы). В некоторых ячейках есть поля, значения которых привязаны к участку, поэтому прежде чем конвертировать поле в текст нужно размножить таблицы.

JohnSUN

Ну, в принципе, я так и подумал... Предметная область другая, но суть та же: по шаблону изготовить документ с данными из какой-то базы и, возможно, сохранить его в DBF (JPEG?) во избежание порчи и подтирок...
Похоже, ты сейчас действительно гребёшь в нужную сторону, но не по скоростной трассе, а по объездной грунтовке.
Ты напрягаешь офис на разметку текстового документа - много возни с кодированием и выполняться будет достаточно долго.
Альтернативный путь: раззиповываешь исходный шаблон, перелопачиваешь content.xml в соответствии с какими-то своими тегами разметки и полученными данными, зазиповываешь обратно в odt и предъявляешь пользователю.
Помниться, в Ananas'е использовался такой приём: можешь мне поверить - скорость формирования просто дикая.
Тем более, что раз уж исходные данные в XML, то и XMLвскую начинку .odt бояться не станешь.
А работу с zip-файлами или см. в  5.31. Extracting a Zip File или крути прямо из Delphi...
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

geopos

Предложенный вариант рассмотрю, но уже слишком много проехал по грунтовке. Тем более все это давно реализовал в Ворде и местами стараюсь делать уникальный код, чтобы процедуры/функции работали с МС и ОО.
Получается, что одт можно представить в ввиде хмл? И общий вопрос относительно графики в Writer - есть ли аналог холста и если я понял правильно насчет содержимого документа в виде хмл, возможно ли рисовать простые примитивы: линии, точки, полигоны,..?

JohnSUN

#12
Цитата: geopos от 15 мая 2015, 19:56
Предложенный вариант рассмотрю, но уже слишком много проехал по грунтовке. Тем более все это давно реализовал в Ворде и местами стараюсь делать уникальный код, чтобы процедуры/функции работали с МС и ОО.
Я тоже потоптался над такой реализацией и плюнул. Просто определяю доступен ли на данной машине ОО и двумя отдельными ветками формирую одни и те же документы.
Цитата: geopos от 15 мая 2015, 19:56Получается, что одт можно представить в ввиде хмл?
Да ты зипом в любой документ загляни - там кроме XMLевских файлов и графики редко что увидишь.
Цитата: geopos от 15 мая 2015, 19:56И общий вопрос относительно графики в Writer - есть ли аналог холста и если я понял правильно насчет содержимого документа в виде хмл, возможно ли рисовать простые примитивы: линии, точки, полигоны,..?
Муторно. Но можно
Sub DrawRedLineInDocument
Dim xPage as Object, xDoc as Object, xShape as Object
Dim aPosition As New com.sun.star.awt.Point
Dim TheSize As New com.sun.star.awt.Size
xDoc = ThisComponent
xPage = xDoc.getDrawPage()
xShape = xDoc.createInstance( "com.sun.star.drawing.LineShape" )
xShape.LineColor = RGB( 255, 0, 0 )
xShape.LineWidth = 100
aPosition.X = 2500
aPosition.Y = 2500
xShape.setPosition(aPosition)
TheSize.width = 2500
TheSize.height=5000
xShape.setSize(TheSize)
xPage.add( xShape )
End Sub

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

geopos

#13
Спасибо! Смотрел и не только... даже пробовал насчет парсинга content.xml, но пока решил не сходить с тропы: осталось доползти на животе несколько метров :) С таблицами вроде как разобрался (попозже буду экспериментировать с CursorAfterCurrentTable) - опять таки пока Спасибо! Даже захотелось угостить пивом. Читал книжку.. увидел мастер поля, интересный метод взятия поля по имени, который намного быстрее чем перебор циклом по всем полям и затем сравнивать их имена с искомым именем. Проблема не могу додумкать как преобразовать поле(значение) в текст: masterfield.Anchor.string := masterfield.Anchor.string выдает ошибку. А казалось бы должно поддерживать интерфейс.

Заметил в документе, в котором игрался с таблицами, тестовые значения полей конвертируются в нули, а числа округляет до десятых. Видимо полям нужно нужно объяснять что это текст TextField.ExtendedUser := Content;

Наверное нужно отдохнуть.. уже сам глючу, а что мне мешает использовать Doc.getTextFields? Оставлю ранее предложенный метод конвертации полей в текст
fields := Doc.getTextFields;    
enum := fields.CreateEnumeration;
   while enum.HasMoreElements do
   begin
     field := enum.nextElement;
     field.Anchor.String := field.Anchor.String;  // здесь НУЛИ в таблице
   end;


Проблема с нулями в таблице пока осталась : ПОЛЕ -> Строка = 0

Вот и разобрался с нулями вот так field.Anchor.String := field.textFieldMaster.Content

JohnSUN

А зачем ты вообще с полями связался? Прямо в документ значения писать не пробовал? Я ведь так понял, что поля ты используешь только для вставки значений, а потом преобразуешь их в текст... Так может сразу - шар-р-рах! - setString? или даже setDataArray?

А по поводу размножающихся однотипных таблиц... Может, все-таки просто вставлять нужное количество строк в одну-единственную таблицу, а разрыв в одну строку имитировать отсутствием обрамления? Ну, или просто разбивать таблицу по указанной строке (тем же .uno:SplitTable, например)
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне