Подтвердить что ты не робот

Добавить правила стилизации в pandoc-таблицах для вывода odt/docx (границы таблицы)

Я генерирую некоторые отчеты odt/docx через markdown с помощью knitr и pandoc, и теперь мне интересно, как вы собираетесь создавать таблицы. В первую очередь меня интересуют добавление правил (по крайней мере, верхний, нижний и один под заголовком, но возможность добавления произвольных внутри таблицы тоже будет приятным).

Выполнение следующего примера из документации pandoc через pandoc (без каких-либо специальных параметров) дает только "обычную" таблицу без каких-либо правил/цветов/направляющих (в -t odt или -t docx).

+---------------+---------------+--------------------+
| Fruit         | Price         | Advantages         |
+===============+===============+====================+
| Bananas       | $1.34         | - built-in wrapper |
|               |               | - bright color     |
+---------------+---------------+--------------------+
| Oranges       | $2.10         | - cures scurvy     |
|               |               | - tasty            |
+---------------+---------------+--------------------+

Я просмотрел "стили" для возможности указания форматирования таблицы в reference.docx/.odt, но не нашел ничего очевидного вне стилей "table header" и "table contents", оба из которых, похоже, касаются только форматирование текста внутри таблицы.

Будучи довольно незнакомым с процессорами документов в стиле WYSIWYG, я теряюсь относительно того, как продолжить.

4b9b3361

Ответ 1

Вот как я искал, как это сделать:

Способ добавления таблицы в Docx заключается в использовании тега <w:tbl>. Поэтому я искал это в репозитории github и нашел его в этом файле (это называется Writers/Docx.hs, так что это не большой сюрприз)

blockToOpenXML opts (Table caption aligns widths headers rows) = do
  let captionStr = stringify caption
  caption' <- if null caption
                 then return []
                 else withParaProp (pStyle "TableCaption")
                      $ blockToOpenXML opts (Para caption)
  let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()
  let cellToOpenXML (al, cell) = withParaProp (alignmentFor al)
                                    $ blocksToOpenXML opts cell
  headers' <- mapM cellToOpenXML $ zip aligns headers
  rows' <- mapM (\cells -> mapM cellToOpenXML $ zip aligns cells)
           $ rows
  let borderProps = mknode "w:tcPr" []
                    [ mknode "w:tcBorders" []
                      $ mknode "w:bottom" [("w:val","single")] ()
                    , mknode "w:vAlign" [("w:val","bottom")] () ]
  let mkcell border contents = mknode "w:tc" []
                            $ [ borderProps | border ] ++
                            if null contents
                               then [mknode "w:p" [] ()]
                               else contents
  let mkrow border cells = mknode "w:tr" [] $ map (mkcell border) cells
  let textwidth = 7920  -- 5.5 in in twips, 1/20 pt
  let mkgridcol w = mknode "w:gridCol"
                       [("w:w", show $ (floor (textwidth * w) :: Integer))] ()
  return $
    [ mknode "w:tbl" []
      ( mknode "w:tblPr" []
        ( [ mknode "w:tblStyle" [("w:val","TableNormal")] () ] ++
          [ mknode "w:tblCaption" [("w:val", captionStr)] ()
          | not (null caption) ] )
      : mknode "w:tblGrid" []
        (if all (==0) widths
            then []
            else map mkgridcol widths)
      : [ mkrow True headers' | not (all null headers) ] ++
      map (mkrow False) rows'
      )
    ] ++ caption'

Я вообще не знаком с Haskell, но я вижу, что пограничный стиль жестко закодирован, поскольку в нем нет переменной:

let borderProps = mknode "w:tcPr" []
                    [ mknode "w:tcBorders" []
                      $ mknode "w:bottom" [("w:val","single")] ()
                    , mknode "w:vAlign" [("w:val","bottom")] () ]

Что это значит?

Это означает, что вы не можете изменить стиль таблиц docx с текущей версией PanDoc. Howwer, есть способ получить свой собственный стиль.

Как получить свой собственный стиль?

  • Создайте документ Docx со стилем, который вы хотите в своей таблице (создав эту таблицу)
  • Измените расширение этого файла и разархивируйте его
  • Откройте word/document.xml и найдите <w:tbl>
  • Попробуйте узнать, как ваш стиль преобразуется в XML и изменяет borderProps в соответствии с тем, что вы видите.

Здесь тест с созданным мной пограничным стилем: Custom border style

И вот соответствующий XML:

<w:tblBorders>
  <w:top w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
  <w:left w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
  <w:bottom w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
  <w:right w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
  <w:insideH w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
  <w:insideV w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
</w:tblBorders>

Как насчет odt?

Я еще не посмотрел на него, спросите, не нашли ли вы сами, используя аналогичный метод.

Надеюсь, что это поможет и не стесняйтесь спрашивать что-то еще.

Ответ 2

Такое же предложение, как edi9999: взломать содержимое xml конвертированного docx. И для этого мне нужен R-код.

В переменной tblPr содержится определение стиля, добавляемого к таблицам в docx. Вы можете изменить строку, чтобы удовлетворить ваши собственные потребности.

require(XML)

docx.file <- "report.docx"
tblPr <- '<w:tblPr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:tblStyle w:val="a8"/><w:tblW w:w="0" w:type="auto"/><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:left w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:right w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/></w:tblBorders><w:jc w:val="center"/></w:tblPr>'

## unzip the docx converted by Pandoc
system(paste("unzip", docx.file, "-d temp_dir"))
document.xml <- "temp_dir/word/document.xml"

doc <- xmlParse(document.xml)
tbl <- getNodeSet(xmlRoot(doc), "//w:tbl")
tblPr.node <- lapply(1:length(tbl), function (i)
                   xmlRoot(xmlParse(tblPr)))
added.Pr <- names(xmlChildren(tblPr.node[[1]]))
for (i in 1:length(tbl)) {
    tbl.node <- tbl[[i]]
    if ('tblPr' %in% names(xmlChildren(tbl.node))) {
        children.Pr <- xmlChildren(xmlChildren(tbl.node)$tblPr)
        for (j in length(added.Pr):1) {
            if (added.Pr[j] %in% names(children.Pr)) {
                replaceNodes(children.Pr[[added.Pr[j]]],
                             xmlChildren(tblPr.node[[i]])[[added.Pr[j]]])
            } else {
                ## first.child <- children.Pr[[1]]
                addSibling(children.Pr[['tblStyle']],
                           xmlChildren(tblPr.node[[i]])[[added.Pr[j]]],
                           after=TRUE)
            }
        }
    } else {
        addSibling(xmlChildren(tbl.node)[[1]], tblPr.node[[i]], after=FALSE)
    }
}

## save hacked xml back to docx
saveXML(doc, document.xml, indent = F)
setwd("temp_dir")
system(paste("zip -r ../", docx.file, " *", sep=""))
setwd("..")
system("rm -fr temp_dir")

Ответ 3

edi9999 имеет лучший ответ, но вот что я делаю:

При создании docx используйте ссылку docx для получения стилей. Эта ссылка будет содержать кучу других стилей, которые просто не используются Pandoc для создания, но они все еще там. Как правило, вы получите настройки по умолчанию, но вы также можете добавить новый стиль таблицы.

Затем вам нужно только обновить файл word\document.xml, чтобы ссылаться на новый стиль таблицы, и вы можете сделать это программно (путем распаковки, запуска sed и обновления архива docx), например:

7z.exe x mydoc.docx word\document.xml
sed "s/<w:tblStyle w:val=\"TableNormal\"/<w:tblStyle w:val=\"NewTableStyle\"/g" word\document.xml > word\document2.xml
copy word\document2.xml word\document.xml /y
7z.exe u mydoc.docx word\document.xml

Ответ 4

добавьте стиль таблицы с именем "TableNormal" в reference.docx.

Ответ 5

Просто добавьте стиль таблицы, что вы хотите назвать "Таблица" в файле reference-doc. И обновите pandoc до последней.

Ответ 6

Использование ссылочного файла docx, а затем python-docx делает работу довольно легко:

https://python-docx.readthedocs.io/

Сначала конвертируйте ваш документ в docx:

Баш:

pandoc --standalone --data-dir=/path/to/reference/ --output=/tmp/xxx.docx input_file.md

Заметки:

  • /path/to/reference/ указывает на папку, содержащую reference.docx
  • reference.docx - это файл, содержащий стили, необходимые для элементов docx.

Затем дайте таблицам вашего документа стиль, который вы хотите использовать:

Python:

import docx
document = docx.Document('/tmp/xxx.docx')
for table in document.tables:
    table.style = document.styles['custom_style'] # custom_style must exist in your reference.docx file