Об'ємні клітини таблиці

Іноді деякі ряди в таблиці вимагають заголовка або великі блоки тексту, які займають повну ширину таблиці. Для належного оформлення таблиці користувач може об’єднати кілька клітин таблиці в одну. 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

Щоб об’єднати клітинки в таблиці, створеному з 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 не використовується, наприклад, в існуючому столі, злиття клітин в попередньому вигляді може бути не так просто. Замість цього ми можемо обгорнути основні операції, що беруть участь у застосуванні об’єднувальних властивостей до клітин в методі, що робить завдання набагато простіше. Цей метод схожий на метод автоматизації Merge, який називається об’єднання діапазону клітин в таблиці.

Введіть номер мобільного, який Ви вказали при укладаннi договору з банком - для ідентифікації. У цьому випадку діапазон може пропускати декілька рядків або стовпців:

// 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й стовпчик” – це те, що “Комплект 1 клітин кожного ряду в таблиці”. Це дозволяє користувачам мати таблицю, в якому, наприклад, 1-й ряд складається з двох клітин – 2см і 1см, а 2-й ряд складається з двох різних клітин – 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();