我正在使用knitr和pandoc通过markdown生成一些odt / docx报告,现在我想知道如何制作表格。主要是我有兴趣添加规则(至少在标题下方的顶部,底部和一个,但是能够在表格中添加任意的规则也很好)。
通过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风格的文档处理器不太熟悉,我对如何继续使用感到很遗憾。
答案 0 :(得分:22)
以下是我搜索如何执行此操作的方法:
在Docx中添加表格的方法是使用<w:tbl>
标记。所以我在github存储库中搜索了这个,发现它in this file(称为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")] () ]
这意味着您无法使用当前版本的PanDoc更改docx表的样式。但是,有一种方法可以让自己的风格。
word/document.xml
并搜索<w:tbl>
这是我创建的边框样式的测试:
这是相应的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>
我还没看好它,问你是不是自己找不到类似的方法。
希望这会有所帮助,并且毫不犹豫地提出更多问题
答案 1 :(得分:10)
与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")
答案 2 :(得分:4)
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
答案 3 :(得分:2)
添加名为&#34; TableNormal&#34;的表样式在reference.docx。
答案 4 :(得分:2)
使用参考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
答案 5 :(得分:1)
只需添加一个表格样式,你想要的就是所谓的#34;表&#34;在reference-doc文件中。并将pandoc更新为最新版本。