2013-07-25 64 views
19

我使用knitr和pandoc通过降价生成一些odt/docx报告,现在想知道如何去化表格。主要是我有兴趣添加规则(至少顶部,底部和标题下方的一个,但能够添加任意表中的内容也会很好)。为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但一无所获明显超越“表头”和“目录”的风格,两者似乎只涉及表格中文本的格式。

对于所见即所得风格的文档处理器而言,我很不熟悉,对于如何继续,我很失落。

回答

20

以下是我寻找如何做到这一点:

添加表的方式DOCX是使用<w:tbl>标签。所以,我搜索了这个在GitHub的仓库,并发现它in this file(称为作家/ 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' 

我不熟悉的所有哈斯克尔,但我可以看到边框样式是硬编码的,因为它没有变量:

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

这是什么意思?

这意味着您无法使用当前版本的PanDoc更改docx表的样式。但是,有一种方法可以获得自己的风格。

如何获得自己的风格?

  1. (通过创建表)
  2. 更改创建您是否想在表中的样式的docx文件该文件的扩展名并解压,
  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?

我还没有看过它,问你是否自己找不到使用类似的方法。

希望这有助于不要犹豫,要求更多的东西

+0

我会接受这个,因为它是第一个。我甚至没有想过简单地检查代码(或者我可能太懒惰了,宁愿让别人去做);)!谢谢! –

+0

当您不熟悉背后发生的事情时,检查代码并不总是那么容易,例如文档是如何构造的,以及如何在docx中表示表格。所以这很正常。 – edi9999

+1

这是一个很好的答案。所有赞扬你@ edi9999。 – Archonic

9

同样的建议为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") 
4

edi9999有最好的答案,但这里是我做的:

在创建的docx,使用引用DOCX得到样式。该参考文件将包含一堆Pandoc未使用的其他样式,但它们仍然存在。通常情况下,您将获得默认设置,但您也可以添加新的表格样式。

然后,您只需要更新字\ 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 
+0

这个答案与--reference-docx =选项结合是一个杀手! – ivarec

2

在reference.docx中添加名为“TableNormal”的表样式。

+0

这对我来说并不奏效,因为Word(2010)抱怨这种风格被保留。 – mkingston

0

只需在reference-doc文件中添加一个表格样式,然后将pandoc更新为最新版本。