2013-07-25 18 views
19

Sto generando alcuni rapporti odt/docx tramite markdown usando knitr e pandoc e sto ora chiedendo come si andrebbe a formattare le tabelle. Principalmente sono interessato ad aggiungere regole (almeno in alto, in basso e una sotto l'intestazione, ma anche la possibilità di aggiungere quelle arbitrarie all'interno del tavolo sarebbe bello).Aggiungere regole di stile nelle tabelle pandoc per output odt/docx (bordi tabella)

L'esecuzione del seguente esempio dalla documentazione di pandoc tramite pandoc (senza parametri speciali) produce semplicemente una tabella "semplice" senza alcun tipo di regole/colori/guide (in -t odt o -t docx).

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

Ho guardato attraverso gli "stili" per la possibilità di specificare tavolo formattazione in un riferimento .docx/.odt ma non trovò nulla evidente al di là di "intestazione di tabella" e "il contenuto della tabella" stili, entrambi i quali sembra riguardare solo la formattazione del testo all'interno del tavolo.

Essendo piuttosto poco familiare con processori di documenti in stile WYSIWYG, mi sono perso su come continuare.

risposta

20

Ecco come ho cercato come fare questo:

Il modo per aggiungere una tabella in Docx è quello di utilizzare il tag <w:tbl>. Così ho cercato per questo nel repository github, e l'ho trovato in this file (chiamati Scrittori/Docx.hs, quindi non è una grande sorpresa)

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' 

io non sono a conoscenza a tutti con Haskell, ma posso vedere che lo stile del bordo è hardcoded, poiché non vi è alcuna variabile in esso:

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

Che cosa significa?

Ciò significa che non è possibile modificare lo stile delle tabelle docx con la versione corrente di PanDoc. In ogni caso, c'è un modo per ottenere il proprio stile.

Come ottenere il proprio stile?

  1. Creare un documento docx con lo stile che si desidera sul vostro tavolo (con la creazione di quel tavolo)
  2. cambiare l'estensione del file e decomprimerlo
  3. Aprire word/document.xml e cercare il <w:tbl>
  4. Try per scoprire come il tuo stile si traduce in XML e cambiare il borderProps in base a ciò che vedi.

Ecco un test con un border-style che ho creato: Custom border style

E qui è il corrispondente 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> 

Che dire odt?

Non ho ancora dato un'occhiata, chiedete se non lo trovate da soli usando un metodo simile.

Spero che questo aiuti e non esitate a chiedere qualcosa di più

+0

Accetterò questo, poiché era il primo. Non ho nemmeno pensato di controllare semplicemente il codice (o forse sono troppo pigro e preferisco lasciare che siano gli altri a farlo;))! Grazie! –

+0

Non è sempre facile controllare il codice quando non si ha familiarità con ciò che accade dietro, ad esempio come è strutturato un documento, come viene rappresentata la tabella in docx. Quindi è normale. – edi9999

+1

Questa è una risposta meravigliosa. Tutti i voti positivi per te @ edi9999. – Archonic

9

stessa suggestione come edi9999: incidere il contenuto XML del docx convertito.E il seguente è il mio codice R per farlo.

La variabile tblPr contiene la definizione di stile da aggiungere alle tabelle in docx. È possibile modificare la stringa per soddisfare le proprie esigenze.

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 ha la risposta migliore, ma qui è quello che faccio:

Quando si crea il docx, utilizzare un docx di riferimento per ottenere gli stili. Quel riferimento conterrà un mucchio di altri stili che non vengono usati da Pandoc per creare, ma sono ancora lì. Generalmente otterrai i set predefiniti, ma puoi anche aggiungere un nuovo stile di tabella.

Poi, è sufficiente aggiornare il file word \ document.xml per fare riferimento alla nuova tabella di stile, e si può fare a livello di codice (da decompressione, in esecuzione sed, e aggiornare l'archivio docx), ad esempio:

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

Questa risposta combinata con l'opzione --reference-docx = è un killer! – ivarec

2

aggiungere uno stile di tabella denominato "TableNormal" in reference.docx.

+0

Questo non ha funzionato per me in quanto Word (2010) si è lamentato dello stile riservato. – mkingston

0

Basta aggiungere uno stile tabella a ciò che si desidera chiamare "Tabella" nel file di riferimento-documento. E aggiornare pandoc a più tardi.