Сливане на клетки от таблица

Понякога някои редове в таблица изискват заглавие или големи блокове текст, които заемат пълната ширина на таблицата. За правилното проектиране на масата, потребителят може да слее няколко клетки на масата в една. Aspose.Words поддържа слетите клетки при работа с всички входни формати, включително импортиране на HTML съдържание.

Как да обединим клетките на таблицата

В Aspose.Words, слетите клетки са представени от следните свойства на CellFormat клас:

  • HorizontalMerge което описва дали клетката е част от хоризонтално сливане на клетки
  • VerticalMerge което описва дали клетката е част от вертикално сливане на клетки

Стойностите на тези свойства определят сливането на поведението на клетките:

  • Първата клетка в поредица от слети клетки ще има CellMerge.First
  • Всички впоследствие слети клетки ще имат CellMerge.Previous
  • Клетка, която не се слива ще има CellMerge.None

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

Проверка дали клетка се свързва

За да проверим дали дадена клетка е част от поредица от слети клетки, просто проверяваме HorizontalMerge както и VerticalMerge имоти.

Следният пример за код показва как да отпечатате типа хоризонтално и вертикално сливане на клетките:

// 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));
}
}

Сливане на таблици клетки при използване на документ строител

Сливане на клетки в таблица, създадена с DocumentBuilder, трябва да зададете подходящия тип сливане за всяка клетка, където сливането се очаква по-рано CellMerge.First и тогава CellMerge.Previous.

Също така, не трябва да забравяте да изчистите настройката за сливане за тези клетки, където не се изисква сливане го може да се направи чрез задаване на първата несливаща се клетка към CellMerge.None. Ако това не стане, всички клетки в таблицата ще бъдат обединени.

Следният пример за код показва как да се създаде таблица с два реда, където клетките в първия ред се сливат хоризонтално:

// 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");

Следният пример за код показва как да се създаде таблица с две колони, в която клетките в първата колона се сливат вертикално:

// 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");

Сливане на таблици клетки в други случаи

В други ситуации, когато DocumentBuilder не се използва, като например в съществуваща таблица, сливане на клетки по предишния начин може да не е толкова лесно. Вместо това можем да увием основните операции, свързани с прилагането на сливане на свойствата на клетките в метод, който прави задачата много по-лесна. Този метод е подобен на метода за сливане автоматизация, който се нарича сливане на набор от клетки в таблица.

Кодът по-долу ще слее клетките на таблицата в определения диапазон, започвайки от дадена клетка и завършвайки в крайната клетка. В този случай обхватът може да обхваща няколко реда или колони:

// 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);
}
}
}
}

Следният пример за код показва как да се слее набор от клетки между две определени клетки:

// 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");

Вертикални и хоризонтални свързващи клетки в HTML таблица

Както казахме в предишните статии, маса в Microsoft Word е набор от независими редове. Всеки ред има набор от клетки, които са независими от клетките на други редове. По този начин в Microsoft Word таблица не съществува такъв обект като готварски, а първата колона е нещо като набор от 1-ви клетки на всеки ред в таблицата. Това позволява на потребителите да имат таблица, в която, например, първият ред се състои от две клетки 2см и 1см, а вторият ред се състои от две различни клетки, които са широки 1см и 2см. И Aspose.Words поддържа тази концепция за масите.

Таблица в HTML има по същество различна структура: всеки ред има еднакъв брой клетки и (това е важно за задачата) всяка клетка има широчината на съответната колона, еднаква за всички клетки в една колона. Така че, ако HorizontalMerge както и VerticalMerge връщане на неправилна стойност, използвайте следния пример с код:

// 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;
}

Конвертиране в хоризонтално положение Разделени клетки

Понякога не е възможно да се открият кои клетки се сливат, защото някои по-нови версии на Microsoft Word вече не използват сливащите се флагове, когато клетките се сливат хоризонтално. Но за ситуации, в които клетките се сливат в клетка хоризонтално с широчината си, използвайки сливащи се флагове, Aspose.Words осигурява ConvertToHorizontallyMergedCells метод за преобразуване на клетки. Този метод просто трансформира таблицата и добавя нови клетки, когато е необходимо.

Следният пример с код показва гореспоменатия метод в действие:

// 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();