ادغام سلول های جدول
گاهی اوقات ردیف های خاصی در یک جدول نیاز به یک عنوان یا بلوک های بزرگ متن دارند که عرض کامل جدول را اشغال می کنند. برای طراحی مناسب جدول، کاربر می تواند چندین سلول جدول را در یک ادغام کند. Aspose.Words از سلول های ادغام شده در هنگام کار با تمام فرمت های ورودی، از جمله وارد کردن محتوای HTML پشتیبانی می کند.
نحوه ادغام سلول های جدول
در Aspose.Words، سلول های ادغام شده با خواص زیر کلاس CellFormat نشان داده می شوند:
- HorizontalMerge که توضیح می دهد که آیا سلول بخشی از ادغام افقی سلول ها است
- VerticalMerge که توصیف می کند که آیا سلول بخشی از ادغام عمودی سلول ها است
مقادیر این خواص رفتار ادغام سلول ها را تعیین می کند:
- اولین سلول در یک دنباله از سلول های ادغام شده خواهد داشت CellMerge.First
- هر سلول ادغام شده بعدی CellMerge.Previousخواهد داشت
- سلولی که ادغام نشده باشد CellMerge.Noneخواهد داشت
بررسی اینکه آیا یک سلول ادغام شده است
برای بررسی اینکه آیا یک سلول بخشی از یک دنباله از سلول های ادغام شده است، ما به سادگی ویژگی های 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 استفاده نمی شود، مانند یک جدول موجود، ادغام سلول ها به روش قبلی ممکن است به همان اندازه آسان نباشد. در عوض، ما می توانیم عملیات اساسی مربوط به استفاده از خواص ادغام به سلول ها را به روشی که کار را بسیار آسان تر می کند، بسته بندی کنیم. این روش شبیه به روش اتوماسیون ادغام است که برای ادغام طیف وسیعی از سلول ها در یک جدول فراخوانده می شود.
کد زیر سلول های جدول را در محدوده مشخص شده ادغام می کند، از سلول داده شده شروع می شود و در سلول نهایی به پایان می رسد. در این حالت، محدوده می تواند چندین ردیف یا ستون را در بر بگیرد:
// 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 چیزی به نام “ستون” وجود ندارد و “ستون اول” چیزی شبیه “مجموعه سلول های اول هر ردیف در جدول"است. این به کاربران اجازه می دهد تا یک جدول داشته باشند که در آن، به عنوان مثال، ردیف اول از دو سلول – 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(); |