Sloučit stolní buňky

Někdy některé řádky v tabulce vyžadují nadpis nebo velké bloky textu, které zabírají celou šířku tabulky. Pro správný návrh tabulky může uživatel sloučit několik buněk tabulky do jedné. Aspose.Words podporuje sloučené buňky při práci se všemi vstupními formáty, včetně importu HTML obsahu.

Jak sloučit stolní buňky

In Aspose.Words, Sloučené buňky jsou zastoupeny následujícími vlastnostmi: CellFormat třída:

  • HorizontalMerge která popisuje, zda je buňka součástí horizontálního sloučení buněk
  • VerticalMerge která popisuje, zda je buňka součástí vertikálního sloučení buněk

Hodnoty těchto vlastností určují slučovací chování buněk:

work-with-merged-cells-aspose-words-java

Kontrola, zda je buňka Meged

Chcete-li zjistit, zda je buňka součástí sekvence sloučených buněk, stačí zkontrolovat HorizontalMerge a VerticalMerge vlastnosti.

Následující příklad kódu ukazuje, jak tisknout horizontální a vertikální typ sloučení buňky:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document(getMyDir() + "Table with merged cells.docx");
Table table = (Table) doc.getChild(NodeType.TABLE, 0, true);
for (Row row : (Iterable<Row>) table.getRows())
{
for (Cell cell : (Iterable<Cell>) row.getCells())
{
System.out.println(printCellMergeType(cell));
}
}

Sloučit stolní buňky při použití nástroje

Sloučit buňky v tabulce vytvořené s DocumentBuilder, Musíte nastavit vhodný typ sloučení pro každou buňku, kde se předpokládá sloučení nejdříve? CellMerge.First a pak CellMerge.Previous.

Musíte také pamatovat na to, abyste vyčistili nastavení sloučení pro ty buňky, kde není nutné sloučit. CellMerge.None. Pokud tomu tak není, všechny buňky v tabulce budou sloučeny.

Následující příklad kódu ukazuje, jak vytvořit tabulku se dvěma řádky, kde jsou buňky v prvním řádku sloučeny vodorovně:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.insertCell();
builder.getCellFormat().setHorizontalMerge(CellMerge.FIRST);
builder.write("Text in merged cells.");
builder.insertCell();
// This cell is merged to the previous and should be empty.
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS);
builder.endRow();
builder.insertCell();
builder.getCellFormat().setHorizontalMerge(CellMerge.NONE);
builder.write("Text in one cell.");
builder.insertCell();
builder.write("Text in another cell.");
builder.endRow();
builder.endTable();
doc.save(getArtifactsDir() + "WorkingWithTables.HorizontalMerge.docx");

Následující příklad kódu ukazuje, jak vytvořit tabulku dvou sloupců, kde jsou buňky v prvním sloupci vertikálně sloučeny:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.insertCell();
builder.getCellFormat().setVerticalMerge(CellMerge.FIRST);
builder.write("Text in merged cells.");
builder.insertCell();
builder.getCellFormat().setVerticalMerge(CellMerge.NONE);
builder.write("Text in one cell");
builder.endRow();
builder.insertCell();
// This cell is vertically merged to the cell above and should be empty.
builder.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS);
builder.insertCell();
builder.getCellFormat().setVerticalMerge(CellMerge.NONE);
builder.write("Text in another cell");
builder.endRow();
builder.endTable();
doc.save(getArtifactsDir() + "WorkingWithTables.VerticalMerge.docx");

Sloučit stolní buňky v jiných případech

V jiných situacích, kdy DocumentBuilder není používán, jako například ve stávající tabulce, slučovací buňky předchozí cestou nemusí být tak snadné. Místo toho můžeme zabalit základní operace, které se podílejí na aplikaci vlastností sloučení na buňky metodou, která tento úkol mnohem usnadňuje. Tato metoda je podobná metodě automatizace sloučení, která se volá ke sloučení řady buněk v tabulce.

Níže uvedený kód sloučí buňky tabulky ve stanoveném rozsahu, počínaje danou buňkou a končí na konci buňky. V tomto případě může rozsah rozdělit více řádků nebo sloupců:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
void mergeCells(Cell startCell, Cell endCell)
{
Table parentTable = startCell.getParentRow().getParentTable();
// Find the row and cell indices for the start and end cell.
Point startCellPos = new Point(startCell.getParentRow().indexOf(startCell),
parentTable.indexOf(startCell.getParentRow()));
Point endCellPos = new Point(endCell.getParentRow().indexOf(endCell), parentTable.indexOf(endCell.getParentRow()));
// Create a range of cells to be merged based on these indices.
// Inverse each index if the end cell is before the start cell.
Rectangle mergeRange = new Rectangle(Math.min(startCellPos.x, endCellPos.y),
Math.min(startCellPos.y, endCellPos.y),
Math.abs(endCellPos.x - startCellPos.x) + 1, Math.abs(endCellPos.y - startCellPos.y) + 1);
for (Row row : parentTable.getRows())
{
for (Cell cell : row.getCells())
{
Point currentPos = new Point(row.indexOf(cell), parentTable.indexOf(row));
// Check if the current cell is inside our merge range, then merge it.
if (mergeRange.contains(currentPos))
{
cell.getCellFormat().setHorizontalMerge(currentPos.x == mergeRange.getX() ? CellMerge.FIRST : CellMerge.PREVIOUS);
cell.getCellFormat().setVerticalMerge(currentPos.y == mergeRange.getY() ? CellMerge.FIRST : CellMerge.PREVIOUS);
}
}
}
}

Následující příklad kódu ukazuje, jak sloučit rozsah buněk mezi dvěma specifikovanými buňkami:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document(getMyDir() + "Table with merged cells.docx");
Table table = doc.getFirstSection().getBody().getTables().get(0);
// We want to merge the range of cells found inbetween these two cells.
Cell cellStartRange = table.getRows().get(0).getCells().get(0);
Cell cellEndRange = table.getRows().get(1).getCells().get(1);
// Merge all the cells between the two specified cells into one.
mergeCells(cellStartRange, cellEndRange);
doc.save(getArtifactsDir() + "WorkingWithTables.MergeCellRange.docx");

Vertikální a horizontální Merged buňky v HTML tabulce

Jak jsme řekli v předchozích článcích, tabulka v Microsoft Word je soubor nezávislých řádků. Každá řada má sadu buněk, které jsou nezávislé na buňkách jiných řádků. Proto v Microsoft Word Tabulka neexistuje takovýto předmět, jako je sloupec To umožňuje uživatelům mít tabulku, v níž například 1. řádek se skládá ze dvou buněk 2cm a 1cm, a 2. řádek se skládá ze dvou různých buněk 1cm a 2cm široké. A Aspose.Words podporuje tento koncept tabulek.

Tabulka v HTML má v podstatě jinou strukturu: každý řádek má stejný počet buněk a (je to důležité pro úkol) každá buňka má šířku odpovídajícího sloupce, stejný pro všechny buňky v jednom sloupci. Takže pokud HorizontalMerge a VerticalMerge vrátit nesprávnou hodnotu, použijte následující příklad kódu:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document(getMyDir() + "Table with merged cells.docx");
SpanVisitor visitor = new SpanVisitor(doc);
doc.accept(visitor);
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
/// <summary>
/// Helper class that contains collection of rowinfo for each row.
/// </summary>
public static class TableInfo
{
public ArrayList<RowInfo> getRows() { return mRows; }
private ArrayList<RowInfo> mRows = new ArrayList<>();
}
/// <summary>
/// Helper class that contains collection of cellinfo for each cell.
/// </summary>
public static class RowInfo
{
public ArrayList<CellInfo> getCells() { return mCells; };
private ArrayList<CellInfo> mCells = new ArrayList<>();
}
/// <summary>
/// Helper class that contains info about cell. currently here is only colspan and rowspan.
/// </summary>
public static class CellInfo
{
public CellInfo(int colSpan, int rowSpan)
{
mColSpan = colSpan;
mRowSpan = rowSpan;
}
public int getColSpan() { return mColSpan; };
private int mColSpan;
public int getRowSpan() { return mRowSpan; };
private int mRowSpan;
}
public static class SpanVisitor extends DocumentVisitor
{
/// <summary>
/// Creates new SpanVisitor instance.
/// </summary>
/// <param name="doc">
/// Is document which we should parse.
/// </param>
public SpanVisitor(Document doc) throws Exception {
mWordTables = doc.getChildNodes(NodeType.TABLE, true);
// We will parse HTML to determine the rowspan and colspan of each cell.
ByteArrayOutputStream htmlStream = new ByteArrayOutputStream();
HtmlSaveOptions options = new HtmlSaveOptions();
{
options.setImagesFolder(System.getProperty("java.io.tmpdir"));
}
doc.save(htmlStream, options);
// Load HTML into the XML document.
org.jsoup.nodes.Document document = Jsoup.parse(htmlStream.toString());
// Get collection of tables in the HTML document.
Elements tables = document.getElementsByTag("table");
for (Element table : tables) {
TableInfo tableInf = new TableInfo();
// Get collection of rows in the table.
Elements rows = table.getElementsByTag("tr");
for (Element row : rows) {
RowInfo rowInf = new RowInfo();
// Get collection of cells.
Elements cells = row.getElementsByTag("td");
for (Element cell : cells) {
// Determine row span and colspan of the current cell.
String colSpanAttr = cell.attributes().get("colspan");
String rowSpanAttr = cell.attributes().get("rowspan");
int colSpan = StringUtils.isNotBlank(colSpanAttr) ? Integer.parseInt(colSpanAttr) : 0;
int rowSpan = StringUtils.isNotBlank(rowSpanAttr) ? Integer.parseInt(rowSpanAttr) : 0;
CellInfo cellInf = new CellInfo(colSpan, rowSpan);
rowInf.getCells().add(cellInf);
}
tableInf.getRows().add(rowInf);
}
mTables.add(tableInf);
}
}
public int visitCellStart(Cell cell)
{
int tabIdx = mWordTables.indexOf(cell.getParentRow().getParentTable());
int rowIdx = cell.getParentRow().getParentTable().indexOf(cell.getParentRow());
int cellIdx = cell.getParentRow().indexOf(cell);
int colSpan = 0;
int rowSpan = 0;
if (tabIdx < mTables.size() &&
rowIdx < mTables.get(tabIdx).getRows().size() &&
cellIdx < mTables.get(tabIdx).getRows().get(rowIdx).getCells().size())
{
colSpan = mTables.get(tabIdx).getRows().get(rowIdx).getCells().get(cellIdx).getColSpan();
rowSpan = mTables.get(tabIdx).getRows().get(rowIdx).getCells().get(cellIdx).getRowSpan();
}
System.out.println(MessageFormat.format("{0}.{1}.{2} colspan={3}\t rowspan={4}", tabIdx, rowIdx, cellIdx, colSpan, rowSpan));
return VisitorAction.CONTINUE;
}
private ArrayList<TableInfo> mTables = new ArrayList<>();
private NodeCollection mWordTables;
}

Převést na horizontálně Mražené buňky

Někdy není možné zjistit, které buňky jsou sloučeny, protože některé novější verze Microsoft Word Pokud jsou buňky sloučeny vodorovně, nesmí již používat vlajky sloučení. Ale pro situace, kdy jsou buňky sloučeny do buňky horizontálně podle jejich šířky pomocí slučovacích vlajek, Aspose.Words poskytuje ConvertToHorizontallyMergedCells způsob přeměny buněk. Tato metoda jednoduše přeměňuje tabulku a přidává nové buňky podle potřeby.

Následující příklad kódu ukazuje výše uvedenou metodu v provozu:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document doc = new Document(getMyDir() + "Table with merged cells.docx");
Table table = doc.getFirstSection().getBody().getTables().get(0);
// Now merged cells have appropriate merge flags.
table.convertToHorizontallyMergedCells();