2016-12-26 6 views
1

Ich habe ein vorhandenes Word-Dokument mit einer Tabelle. Die erste Zeile der Tabelle hat zwei Zellen, aber alle anderen Zeilen haben vier Zellen und jede Zelle hat eine andere Breite.Apache POI - Wie richtige Spaltenbreite in Word-Tabelle

Ich muss neue Zeilen über POI einfügen, die auch vier Zellen mit Breiten haben, die mit denen der vorhandenen 4-Zellen-Zeilen übereinstimmen.

Der Grundcode ist:

XWPFTable table = doc.getTableArray(0); 

XWPFTableRow oldRow = table.getRow(2); 
table.insertNewTableRow(3); 
XWPFTableRow newRow = table.getRow(3); 

XWPFTableCell cell; 
for (int i = 0; i < oldRow.getTableCells().size(); i++) { 
    cell = newRow.createCell(); 
    CTTblWidth cellWidth = cell.getCTTc().addNewTcPr().addNewTcW(); 
    BigInteger width = oldRow.getCell(i).getCTTc().getTcPr().getTcW().getW(); 

    cellWidth.setW(width); // sets width 

    XWPFRun run = cell.getParagraphs().get(0).createRun(); 
    run.setText("NewRow C" + i); 

} 

Das Ergebnis davon ist, dass die Reihe 3 vier Zellen aufweist, aber ihre Breiten als die nicht gleich sind die die Reihe 2. Die Gesamtbreite neue Zeile endet überein Gesamtbreite der ersten drei Zellen der Zeile 2. (Tut mir leid, ich weiß nicht, wie Sie die Word-Tabelle hier einfügen).

Wenn ich jedoch zuerst das Quelldokument manuell bearbeiten, so dass die erste Tabellenzeile auch vier Zellen hat, dann funktioniert alles perfekt. Wenn ich eine Referenz auf eine bestehende Zeile bekomme und sie zur Tabelle hinzufüge, sind die Zellbreiten ebenfalls korrekt (aber ich habe das gleiche Zeilenobjekt zweimal und kann es daher nicht ändern).

Es scheint, dass die Anzahl der Zellen in der ersten Zeile beeinflusst, wie andere Zeilen eingefügt werden. Macht das irgendjemanden Sinn und können Sie vorschlagen, wie man es überschreibt? Gibt es irgendwo ein Dokument, das ich studieren kann, um zu verstehen, wie das funktioniert? Vielen Dank.

+0

Der Tabellencode ein wenig flippig jetzt ist. Es fügt Zellen mit leeren Absätzen für Sie hinzu, so dass Ihr Code am Ende der Zeile, die von 'table.insertNewTableRow (3)' erstellt wurde, hinzugefügt wird. Diese Zeile enthält eine Zelle, die einen Absatz enthält, mit dem Sie beginnen können. Sie werden derzeit Code suchen müssen.Du könntest die neueste Version ausprobieren, die vielleicht etwas besser funktioniert, aber ich denke nicht, dass es noch Korrekturen für den Tabellencode gibt. Am besten ist es, durch sie zu debuggen, um festzustellen, was passiert. – jmarkmurphy

Antwort

1

Entsprechend Ihrer Erwähnung: "Die erste Reihe der Tabelle hat zwei Zellen, aber alle anderen Reihen haben vier Zellen und jede Zelle hat eine andere Breite." Ich vermute, das wird ein sehr chaotischer Tisch sein. Obwohl Word solche Tabellen unterstützt, würde ich versuchen, solche zu vermeiden. Aber wenn es sein muss, müssen Sie wissen, dass es auch für diese chaotischen Tabellen ein Tabellenraster gibt. Entpacken Sie die *.docx und schauen Sie sich /word/document.xml dort finden Sie es.

Also, wenn wir Zeilen in solche chaotischen Tabellen einfügen wollen, müssen wir auch das Tabellenraster respektieren. Dazu gibt es ein GridSpan Element in der CTTcPr. Dies müssen wir auch von der oldRow kopieren und nicht nur die CTTblWidth kopieren.

Auch die CTTblWidth hat nicht nur eine Breite sondern auch einen Typ. Das sollten wir auch kopieren.

Beispiel:

Die source.docx sieht wie folgt aus:

enter image description here

Wie Sie das Tabellengitter hat 10 Spalten insgesamt zu sehen. "Zelle 2 1" umfasst 3 Spalten, "Zelle 2 2" umfasst 3 Spalten, "Zelle 2 3" überspannt 0 Spalten (ist eine eigene Spalte), "Zelle 2 4" umfasst 3 Spalten.

Mit Code:

import java.io.*; 
import org.apache.poi.xwpf.usermodel.*; 
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; 
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; 

import java.math.BigInteger; 

public class WordInsertTableRow { 

public static void main(String[] args) throws IOException, InvalidFormatException { 

    XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx")); 

    XWPFTable table = doc.getTableArray(0); 

    XWPFTableRow oldRow = table.getRow(2); 
    table.insertNewTableRow(3); 
    XWPFTableRow newRow = table.getRow(3); 

    XWPFTableCell cell; 
    for (int i = 0; i < oldRow.getTableCells().size(); i++) { 
    cell = newRow.createCell(); 

    CTTcPr ctTcPr = cell.getCTTc().addNewTcPr(); 

    CTTblWidth cellWidth = ctTcPr.addNewTcW(); 
    cellWidth.setType(oldRow.getCell(i).getCTTc().getTcPr().getTcW().getType()); // sets type of width 
    BigInteger width = oldRow.getCell(i).getCTTc().getTcPr().getTcW().getW(); 
    cellWidth.setW(width); // sets width 

    if (oldRow.getCell(i).getCTTc().getTcPr().getGridSpan() != null) { 
    ctTcPr.setGridSpan(oldRow.getCell(i).getCTTc().getTcPr().getGridSpan()); // sets grid span if any 
    } 

    XWPFRun run = cell.getParagraphs().get(0).createRun(); 
    run.setText("NewRow C" + i); 
    } 

    doc.write(new FileOutputStream("result.docx")); 
    doc.close(); 

    System.out.println("Done"); 

} 
} 

Die result.docx wie folgt aussieht:

enter image description here

+0

Axel Richter - eine sehr nützliche Antwort. Entpacken der .docx war neu für mich und wird sehr hilfreich bei der Lösung zukünftiger Probleme sein. – Grayman

+0

Was ich im Grunde versuche zu tun ist eine Zeile mit ähnlichen Eigenschaften in die darüber liegende Zeile einzufügen, aber den Text, Schriftart und Schattierung zu ändern. Idealerweise würde es eine "Kopienzeile" -Funktion geben, die einen tiefen Klon der Breite, des Breitentyps, der Gitterweite, der Grenzen und der Absätze/Läufe-Objekte ausführen würde. Vermutlich existiert das nicht und es liegt an mir, dieses Klonen für irgendwelche Objekte zu implementieren, die ich modifizieren möchte? – Grayman

+0

Ja, "Apache Poi" im Allgemeinen und "XWPF" im Besonderen ist bis jetzt in Entwicklung. Vielleicht wird diese Kopienzeilenmethode in Zukunft existieren. Aber in aktuellen Versionen existiert es nicht. Also ja, Sie müssen es selbst implementieren. Auch die Low-Level-Objekte 'org.openxmlformats.schemas.wordprocessingml.x2006.main. *' Werden oft benötigt. Für mich [http://grepcode.com] (http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/) hat sich als eine gute Quelle sein der Dokumentation. Dort sind alle Objekte und Methoden verknüpft und so kann man per Mausklick von Methode zu Methode wechseln. –