web-dev-qa-db-ja.com

odt / docx出力(テーブルの境界線)のスタイルルールをpandocテーブルに追加

Knitrとpandocを使用してマークダウンを介していくつかのodt/docxレポートを生成していますが、テーブルのフォーマットをどのように行うのか疑問に思っています。主にルールを追加することに興味があります(少なくともヘッダーの上、下、下に1つありますが、テーブル内に任意のルールを追加できると便利です)。

次の例をpandocドキュメントからpandocを介して(特別なパラメータなしで)実行すると、ルール/色/ガイドのない「プレーン」テーブルが生成されます(いずれかの-t odtまたは-t docx)。

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

参照.docx/.odtでテーブルのフォーマットを指定する可能性について「スタイル」を調べましたが、「テーブルヘッダー」と「テーブルの内容」のスタイル以外に明らかなものは何も見つかりませんでした。どちらも、テーブル内のテキスト。

WYSIWYGスタイルのドキュメントプロセッサに慣れていないので、続行する方法がわかりません。

21
Tilo Wiklund

これを行う方法を検索した方法は次のとおりです。

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にまったく精通していませんが、変数がないため、border-styleがハードコーディングされていることがわかります。

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

どういう意味ですか ?

つまり、現在のバージョンのPanDocではdocxテーブルのスタイルを変更できません。しかし、あなた自身のスタイルを手に入れる方法があります。

あなた自身のスタイルを手に入れる方法は?

  1. テーブルに必要なスタイルでDocxドキュメントを作成します(そのテーブルを作成することにより)
  2. そのファイルの拡張子を変更し、解凍します
  3. Word/document.xmlを開き、<w:tbl>を検索します
  4. スタイルが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はどうですか?

私はまだそれを見ていませんでした、あなたが同様の方法を使ってあなた自身で見つけないかどうか尋ねてください。

これがお役に立てば幸いです。もっと質問することを躊躇しないでください

23
edi9999

Edi9999と同じ提案:変換されたdocxのxmlコンテンツをハックします。そして、以下はそれを行うための私の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")
10
lcn

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
gbjbaanb

reference.docxに「TableNormal」という名前のテーブルスタイルを追加します。

2
henry

参照docxファイルを使用してからpython-docxを使用すると、非常に簡単に作業を実行できます。

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

まず、ドキュメントをdocxに変換します。

Bash:

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
2
Loïc

Reference-docファイルに「Table」と呼ばれるテーブルスタイルを追加するだけです。pandocを最新のものに更新します。

1
ZHUOQI LI