2013-07-25 26 views
19

Generuję niektóre raporty odt/docx za pomocą przecinania za pomocą knitr i pandoc i zastanawiam się teraz, w jaki sposób zajmowałbyś się formatowaniem tabel. Przede wszystkim jestem zainteresowany dodaniem reguł (przynajmniej górny, dolny i jeden pod nagłówkiem, ale możliwość dodania dowolnych wewnątrz tabeli też byłaby miła).Dodanie reguł stylizacji w tabelach pandoc dla wyjścia odt/docx (granice tabel)

Running następujący przykład z dokumentacji pandoc poprzez pandoc (bez dodatkowych parametrów) tylko daje „zwykły” stół bez jakichkolwiek przepisów/kolory/przewodników (w obu -t odt lub -t docx).

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

Szukałem poprzez „style” możliwość określania formatowania tabeli w odniesieniu .docx/odt, ale nic nie znalazłem poza oczywistą „nagłówku tabeli” i „zawartość tabeli” stylów, z których oba wydają się dotyczyć tylko formatowania tekstu w tabeli.

Będąc raczej obeznanym z procesorami dokumentów w stylu WYSIWYG, zagubiłem się, aby kontynuować.

Odpowiedz

20

Oto jak szukałem jak to zrobić:

The sposób dodać tabelę w Docx jest użycie znacznika <w:tbl>. Więc szukałem tego w repozytorium github i znalazł go in this file (tzw Writers/Docx.hs, więc to nie jest wielka niespodzianka)

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' 

nie jestem obeznany w ogóle z Haskell, ale widzę, że styl graniczny jest zakodowany, ponieważ nie ma w nim żadnej zmiennej:

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

Co to znaczy?

Oznacza to, że nie można zmienić stylu tabel docx za pomocą bieżącej wersji PanDoc. Istnieje jednak sposób na zdobycie własnego stylu.

Jak uzyskać własny styl?

  1. utworzyć dokument docx ze stylem chcesz na stole (poprzez tworzenie tej tabeli)
  2. zmienić rozszerzenie tego pliku i rozpakuj go
  3. Otwórz word/document.xml i poszukać <w:tbl>
  4. Try aby dowiedzieć się, jak twój styl przekłada się na XML i zmieniać borderProps zgodnie z tym, co widzisz.

Oto test z pogranicza stylu utworzonego: Custom border style

I tu jest odpowiedź 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> 

Co odt?

Nie obejrzałem jeszcze tego, zapytaj, czy nie znajdziesz sam, używając podobnej metody.

Nadzieja to pomaga i nie wahaj się prosić coś więcej

+0

Zaakceptuję ten, ponieważ był pierwszy. Nie myślałem nawet o sprawdzeniu kodu (a może po prostu jestem zbyt leniwy i wolę pozwolić innym to zrobić;))! Dzięki! –

+0

Nie zawsze łatwo jest sprawdzić kod, gdy nie wiesz, co dzieje się z tyłu, np. W jaki sposób dokument jest zorganizowany, w jaki sposób tabela jest reprezentowana w docx. Więc to normalne. – edi9999

+1

To jest cudowna odpowiedź. Wszystkie upvotes do ciebie @ edi9999. – Archonic

9

tę samą propozycję jako edi9999: włamywanie zawartość xml przebudowanej docx.A oto mój kod R do tego.

Zmienna tblPr zawiera definicję stylu, który należy dodać do tabel w docx. Można zmodyfikować ciąg, aby zaspokoić własne potrzeby.

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 ma najlepszą odpowiedź, ale tutaj jest to, co robię:

Tworząc docx, użyj docx odniesienia, aby uzyskać style. Odniesienie to będzie zawierało mnóstwo innych stylów, które nie są używane przez Pandoc do tworzenia, ale wciąż tam są. Zazwyczaj dostaniesz zestawy domyślne, ale możesz też dodać nowy styl tabeli.

Następnie wystarczy tylko zaktualizować plik słowo \ document.xml aby odwołać nowy styl tabeli, a można to zrobić programowo (przez rozpakowywania, bieganie sed i aktualizowania archiwum docx), np:

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

Ta odpowiedź w połączeniu z opcją --reference-docx = jest zabójcą! – ivarec

2

dodać styl tabeli o nazwie "TableNormal" w pliku reference.docx.

+0

To nie zadziałało, ponieważ Word (2010) skarżył się, że ten styl jest zarezerwowany. – mkingston

0

Po prostu dodaj styl tabeli, który chcesz nazwać "Tabelą" w pliku referencji-doc.And update pandoc to latest.