テーブルセルの結合

テーブル内の特定の行には、テーブルの全幅を占める見出しまたは大きなテキストブロックが必要な場合があります。 テーブルを適切に設計するために、ユーザーは複数のテーブルセルを1つにマージできます。 Aspose.Wordsは、HTMLコンテンツのインポートを含むすべての入力形式を操作するときに、マージされたセルをサポートします。

テーブルセルをマージする方法

Aspose.Wordsでは、マージされたセルはCellFormatクラスの次のプロパティで表されます:

  • HorizontalMergeセルがセルの水平方向のマージの一部であるかどうかを説明します
  • VerticalMergeは、セルがセルの垂直マージの一部であるかどうかを表します

これらのプロパティの値によって、セルのマージ動作が決まります:

  • マージされたセルのシーケンスの最初のセルにはCellMerge.Firstがあります
  • その後にマージされたセルはCellMerge.Previousになります
  • マージされていないセルにはCellMerge.Noneがあります

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

セルがマージされているかどうかの確認

セルがマージされたセルのシーケンスの一部であるかどうかを確認するには、HorizontalMergeVerticalMergeプロパティを確認するだけです。

次のコード例は、水平方向と垂直方向のセルのマージの種類を印刷する方法を示しています:

// 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に設定することで実行できます。 これを行わないと、テーブル内のすべてのセルがマージされます。

次のコード例は、最初の行のセルが水平方向にマージされる2つの行を持つテーブルを作成する方法を示しています:

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

次のコード例は、最初の列のセルが垂直方向にマージされる2列のテーブルを作成する方法を示しています:

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

次のコード例は、指定した2つのセルの間でセルの範囲をマージする方法を示しています:

// 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行目が2cmと1cmの2つのセルで構成され、2行目が1cmと2cmの幅の2つの異なるセルで構成されるテーブルを持つ そしてAspose.Wordsはこのテーブルの概念をサポートしています。

HTML のテーブルは本質的に異なる構造を持ちます。各行には同じ数のセルがあり、(タスクにとって重要なことですが) 各セルの幅は対応する列の幅で、1 つの列内のすべてのセルの幅は同じです。したがって、HorizontalMergeVerticalMerge が誤った値を返す場合は、次のコード例を使用します。

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