2013-07-25 13 views
19

Ich erzeuge einige odt/docx-Berichte über Markdown mit knitr und pandoc und frage mich nun, wie man Tabellen formatieren würde. Hauptsächlich bin ich daran interessiert, Regeln hinzuzufügen (zumindest oben, unten und eine unterhalb der Kopfzeile, aber es wäre auch schön, beliebige in die Tabelle einfügen zu können).Hinzufügen von Stilregeln in Pandoc-Tabellen für odt/docx-Ausgabe (Tabellenrahmen)

Das Ausführen des folgenden Beispiels aus der Pandoc-Dokumentation über Pandoc (ohne spezielle Parameter) ergibt nur eine "normale" Tabelle ohne jegliche Art von Regeln/Farben/Hilfslinien (entweder -t odt oder -t docx).

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

Ich habe die Möglichkeit durch die „Stile“ sehe der Angabe Tabelle Formatierung in einer Referenz .docx/ODT aber nichts offensichtlich über „Tabellenkopf“ gefunden und „Tabelleninhalte“ Stile, von denen beide scheinen nur die Formatierung von Text innerhalb der Tabelle zu betreffen.

Da ich mit WYSIWYG-artigen Dokumentprozessoren eher nicht vertraut bin, bin ich verloren, wie ich weitermachen soll.

Antwort

20

Hier ist, wie ich gesucht, wie dies zu tun:

Die Art und Weise eine Tabelle hinzuzufügen, in Docx den <w:tbl> Tag zu verwenden ist. Also suchte ich diese im Github-Repository, und fand es in this file (genannt Writers/Docx.hs, so ist es keine große Überraschung ist)

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' 

Ich bin nicht vertraut überhaupt mit Haskell, aber ich kann sehen, dass der Rahmenstil fest codiert ist, da keine Variable darin enthalten ist:

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

Was bedeutet das?

Das bedeutet, dass Sie den Stil der docx-Tabellen mit der aktuellen Version von PanDoc nicht ändern können. Howewer, es gibt einen Weg, um Ihren eigenen Stil zu bekommen.

Wie bekommt man seinen eigenen Stil?

  1. erstellen docx-Dokument mit dem Stil, den Sie auf Ihrem Tisch wollen (durch diese Tabelle erstellen)
  2. Ändern Sie die Erweiterung der Datei und entpacken Sie es
  3. öffnen word/document.xml und die Suche nach dem <w:tbl>
  4. Try Finden Sie heraus, wie Ihr Stil in XML übersetzt wird, und ändern Sie die borderProps nach dem, was Sie sehen.

Hier ist ein Test mit einem Rand-Stil, den ich erstellt: Custom border style

Und hier ist die entsprechende 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> 

Was odt?

Ich habe es noch nicht angesehen, fragen Sie, ob Sie nicht selbst eine ähnliche Methode finden.

hoffe, das hilft und zögern Sie nicht, etwas mehr

+0

Ich werde dieses akzeptieren, da es das erste war. Ich habe nicht einmal daran gedacht, den Code einfach zu überprüfen (oder vielleicht bin ich einfach zu faul und lasse es lieber von anderen tun;))! Vielen Dank! –

+0

Es ist nicht immer so einfach, den Code zu überprüfen, wenn Sie nicht wissen, was sich dahinter verbirgt, zB wie ein Dokument strukturiert ist und wie die Tabelle in docx dargestellt wird. Es ist also normal. – edi9999

+1

Das ist eine wunderbare Antwort. Alle upvotes zu dir @ edi9999. – Archonic

9

Same Vorschlag als edi9999 zu fragen: hacken den XML-Inhalt von konvertierten docx.Und das Folgende ist mein R-Code dafür.

Die Variable tblPr enthält die Definition des Stils, der den Tabellen in docx hinzugefügt werden soll. Sie könnten die Zeichenfolge ändern, um Ihren eigenen Bedarf zu decken.

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 hat die beste Antwort, aber hier ist, was ich tue:

Wenn die docx erstellen, verwenden Sie einen Verweis docx Arten zu erhalten. Diese Referenz enthält einen Haufen anderer Stile, die von Pandoc nicht zum Erstellen verwendet werden, aber sie sind immer noch da. Normalerweise erhalten Sie die Standardsätze, aber Sie können auch einen neuen Tabellenstil hinzufügen.

Dann müssen Sie nur das Wort \ document.xml Datei aktualisieren, um die neuen Tabellenstil zu verweisen, und Sie können das programmatisch tun (durch Entpacken läuft sed, und die Aktualisierung des docx-Archiv), zB:

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

Diese Antwort kombiniert mit der Option --reference-docx = ist ein Mörder! – ivarec

2

fügen Sie einen Tabellenstil namens "TableNormal" in reference.docx hinzu.

+0

Dies funktionierte nicht für mich, da Word (2010) darüber klagte, dass dieser Stil reserviert wurde. – mkingston

0

Fügen Sie einfach einen Tabellenstil hinzu, den Sie in der Datei "reference-doc" als "Tabelle" bezeichnen möchten. Und aktualisieren Sie pandoc auf den neuesten Stand.