Saamvlans Tabel Selle

Soms vereis sekere rye in’n tabel’n kop of groot blokke teks wat die volle breedte van die tabel beslaan. Vir behoorlike ontwerp van die tabel, kan die gebruiker verskeie tabel selle saamvoeg in een. Aspose.Words ondersteun saamgesmelte selle wanneer jy met alle invoerformate werk, insluitend die invoer van HTML inhoud.

Hoe Om Tabel Selle Saam Te Voeg

In Aspose.Words word saamgesmelte selle verteenwoordig deur die volgende eienskappe van die CellFormat klas:

  • HorizontalMerge wat beskryf of die sel deel is van’n horisontale samesmelting van selle
  • VerticalMerge wat beskryf of die sel deel is van’n vertikale samesmelting van selle

Die waardes van hierdie eienskappe bepaal die samesmelting gedrag van selle:

Kyk of Sel Saamgesmelt Is

Om te kyk of’n sel deel is van’n reeks saamgesmelte selle, kyk ons eenvoudig na die eienskappe HorizontalMerge en VerticalMerge.

Die volgende kode voorbeeld toon hoe om die horisontale en vertikale sel samesmelting tipe druk:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>(MyDir + u"Table with merged cells.docx");
auto table = System::ExplicitCast<Table>(doc->GetChild(NodeType::Table, 0, true));
for (const auto& row : System::IterateOver<Row>(table->get_Rows()))
{
for (const auto& cell : System::IterateOver<Cell>(row->get_Cells()))
{
std::cout << PrintCellMergeType(cell) << std::endl;
}
}

Saamgevoegde Selle in’n Tabel

Om selle saam te voeg in’n tabel wat met die DocumentBuilder geskep is, moet jy die toepaslike samesmeltingstipe stel vir elke sel waar die samesmelting verwag word – eers CellMerge.First en dan CellMerge.Previous.

Jy moet ook onthou om die samesmelting instelling vir die selle waar geen samesmelting nodig is skoon te maak - dit kan gedoen word deur die eerste nie-samesmelting sel te stel om CellMerge.None. As dit nie gedoen word nie, sal alle selle in die tabel saamgesmelt word.

Die volgende kode voorbeeld toon hoe om’n tabel met twee rye waar die selle in die eerste ry horisontaal saamgesmelt skep:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->InsertCell();
builder->get_CellFormat()->set_HorizontalMerge(CellMerge::First);
builder->Write(u"Text in merged cells.");
builder->InsertCell();
// This cell is merged to the previous and should be empty.
builder->get_CellFormat()->set_HorizontalMerge(CellMerge::Previous);
builder->EndRow();
builder->InsertCell();
builder->get_CellFormat()->set_HorizontalMerge(CellMerge::None);
builder->Write(u"Text in one cell.");
builder->InsertCell();
builder->Write(u"Text in another cell.");
builder->EndRow();
builder->EndTable();
doc->Save(ArtifactsDir + u"WorkingWithTables.HorizontalMerge.docx");

Die volgende kode voorbeeld toon hoe om’n twee-kolom tabel te skep waar die selle in die eerste kolom vertikaal saamgesmelt:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
builder->InsertCell();
builder->get_CellFormat()->set_VerticalMerge(CellMerge::First);
builder->Write(u"Text in merged cells.");
builder->InsertCell();
builder->get_CellFormat()->set_VerticalMerge(CellMerge::None);
builder->Write(u"Text in one cell");
builder->EndRow();
builder->InsertCell();
// This cell is vertically merged to the cell above and should be empty.
builder->get_CellFormat()->set_VerticalMerge(CellMerge::Previous);
builder->InsertCell();
builder->get_CellFormat()->set_VerticalMerge(CellMerge::None);
builder->Write(u"Text in another cell");
builder->EndRow();
builder->EndTable();
doc->Save(ArtifactsDir + u"WorkingWithTables.VerticalMerge.docx");

Voeg Tabel Selle saam In ander Gevalle

In ander situasies waar die DocumentBuilder nie gebruik word nie, soos in’n bestaande tabel, kan die samesmelting van selle op die vorige manier nie so maklik wees nie. In plaas daarvan kan ons die basiese bedrywighede wat betrokke is by die toepassing van samesmelting eienskappe aan selle in’n metode wat die taak baie makliker maak. Hierdie metode is soortgelyk aan die Samesmelting outomatisering metode, wat genoem word om’n reeks selle in’n tabel saam te smelt.

Die kode hieronder sal die tabel selle in die gespesifiseerde reeks saamvoeg, begin by die gegewe sel en eindig by die einde sel. In hierdie geval kan die reeks oor verskeie rye of kolomme strek:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
void MergeCells(SharedPtr<Cell> startCell, SharedPtr<Cell> endCell)
{
SharedPtr<Table> parentTable = startCell->get_ParentRow()->get_ParentTable();
// Find the row and cell indices for the start and end cell.
System::Drawing::Point startCellPos(startCell->get_ParentRow()->IndexOf(startCell), parentTable->IndexOf(startCell->get_ParentRow()));
System::Drawing::Point endCellPos(endCell->get_ParentRow()->IndexOf(endCell), parentTable->IndexOf(endCell->get_ParentRow()));
// Create a range of cells to be merged based on these indices.
// Inverse each index if the end cell is before the start cell.
System::Drawing::Rectangle mergeRange(
System::Math::Min(startCellPos.get_X(), endCellPos.get_X()), System::Math::Min(startCellPos.get_Y(), endCellPos.get_Y()),
System::Math::Abs(endCellPos.get_X() - startCellPos.get_X()) + 1, System::Math::Abs(endCellPos.get_Y() - startCellPos.get_Y()) + 1);
for (const auto& row : System::IterateOver<Row>(parentTable->get_Rows()))
{
for (const auto& cell : System::IterateOver<Cell>(row->get_Cells()))
{
System::Drawing::Point currentPos(row->IndexOf(cell), parentTable->IndexOf(row));
// Check if the current cell is inside our merge range, then merge it.
if (mergeRange.Contains(currentPos))
{
cell->get_CellFormat()->set_HorizontalMerge(currentPos.get_X() == mergeRange.get_X() ? CellMerge::First : CellMerge::Previous);
cell->get_CellFormat()->set_VerticalMerge(currentPos.get_Y() == mergeRange.get_Y() ? CellMerge::First : CellMerge::Previous);
}
}
}
}
view raw merge-cells.h hosted with ❤ by GitHub

Die volgende kode voorbeeld toon hoe om’n reeks selle tussen twee gespesifiseerde selle saam te smelt:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>(MyDir + u"Table with merged cells.docx");
SharedPtr<Table> table = doc->get_FirstSection()->get_Body()->get_Tables()->idx_get(0);
// We want to merge the range of cells found inbetween these two cells.
SharedPtr<Cell> cellStartRange = table->get_Rows()->idx_get(0)->get_Cells()->idx_get(0);
SharedPtr<Cell> cellEndRange = table->get_Rows()->idx_get(1)->get_Cells()->idx_get(1);
// Merge all the cells between the two specified cells into one.
MergeCells(cellStartRange, cellEndRange);
doc->Save(ArtifactsDir + u"WorkingWithTables.MergeCellRange.docx");

Afhangende van die Weergawe van die Raamwerk wat jy gebruik, wil jy dalk hierdie metode verfyn deur dit in’n uitbreidingsmetode te verander. In hierdie geval kan jy hierdie metode direk op’n sel noem om’n reeks selle saam te voeg, soos cell1.Merge(cell2).

Vertikale En Horisontale Saamgevoegde Selle in’n Tabel

Soos ons in vorige artikels gesê het, is’n tabel in Microsoft Word ‘n stel onafhanklike rye. Elke ry het’n stel selle wat onafhanklik is van die selle van ander rye. In die Microsoft Word tabel is daar dus nie so’n voorwerp soos’n “kolom” nie, en “1st kolom” is iets soos “die versameling van die 1st selle van elke ry in die tabel”. Dit laat gebruikers toe om’n tabel te hê waarin byvoorbeeld die 1st ry bestaan uit twee selle 2cm en 1cm, en die 2nd ry bestaan uit twee verskillende selle 1cm en 2cm breed. En Aspose.Words ondersteun hierdie konsep van tabelle.

‘n tabel in HTML het’n wesenlik ander struktuur: elke ry het dieselfde aantal selle en (dit is belangrik vir die taak) elke sel het die breedte van die ooreenstemmende kolom, dieselfde vir alle selle in een kolom. So as HorizontalMerge en VerticalMerge ‘n verkeerde waarde terug te keer, gebruik die volgende kode voorbeeld:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>(MyDir + u"Table with merged cells.docx");
auto visitor = MakeObject<WorkingWithTables::SpanVisitor>(doc);
doc->Accept(visitor);
// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
/// <summary>
/// Helper class that contains collection of rowinfo for each row.
/// </summary>
class TableInfo : public System::Object
{
public:
SharedPtr<System::Collections::Generic::List<SharedPtr<WorkingWithTables::RowInfo>>> get_Rows()
{
return mRows;
}
TableInfo() : mRows(MakeObject<System::Collections::Generic::List<SharedPtr<WorkingWithTables::RowInfo>>>())
{
}
private:
SharedPtr<System::Collections::Generic::List<SharedPtr<WorkingWithTables::RowInfo>>> mRows;
};
/// <summary>
/// Helper class that contains collection of cellinfo for each cell.
/// </summary>
class RowInfo : public System::Object
{
public:
SharedPtr<System::Collections::Generic::List<SharedPtr<WorkingWithTables::CellInfo>>> get_Cells()
{
return mCells;
}
RowInfo() : mCells(MakeObject<System::Collections::Generic::List<SharedPtr<WorkingWithTables::CellInfo>>>())
{
}
private:
SharedPtr<System::Collections::Generic::List<SharedPtr<WorkingWithTables::CellInfo>>> mCells;
};
/// <summary>
/// Helper class that contains info about cell. currently here is only colspan and rowspan.
/// </summary>
class CellInfo : public System::Object
{
public:
int get_ColSpan()
{
return pr_ColSpan;
}
int get_RowSpan()
{
return pr_RowSpan;
}
CellInfo(int colSpan, int rowSpan) : pr_ColSpan(0), pr_RowSpan(0)
{
pr_ColSpan = colSpan;
pr_RowSpan = rowSpan;
}
private:
int pr_ColSpan;
int pr_RowSpan;
};
class SpanVisitor : public DocumentVisitor
{
public:
/// <summary>
/// Creates new SpanVisitor instance.
/// </summary>
/// <param name="doc">
/// Is document which we should parse.
/// </param>
SpanVisitor(SharedPtr<Document> doc) : mTables(MakeObject<System::Collections::Generic::List<SharedPtr<WorkingWithTables::TableInfo>>>())
{
mWordTables = doc->GetChildNodes(NodeType::Table, true);
// We will parse HTML to determine the rowspan and colspan of each cell.
auto htmlStream = MakeObject<System::IO::MemoryStream>();
auto options = MakeObject<Aspose::Words::Saving::HtmlSaveOptions>();
options->set_ImagesFolder(System::IO::Path::GetTempPath());
doc->Save(htmlStream, options);
// Load HTML into the XML document.
auto xmlDoc = MakeObject<System::Xml::XmlDocument>();
htmlStream->set_Position(0);
xmlDoc->Load(htmlStream);
// Get collection of tables in the HTML document.
SharedPtr<System::Xml::XmlNodeList> tables = xmlDoc->get_DocumentElement()->GetElementsByTagName(u"table");
for (const auto& table : System::IterateOver(tables))
{
auto tableInf = MakeObject<WorkingWithTables::TableInfo>();
// Get collection of rows in the table.
SharedPtr<System::Xml::XmlNodeList> rows = table->SelectNodes(u"tr");
for (const auto& row : System::IterateOver(rows))
{
auto rowInf = MakeObject<WorkingWithTables::RowInfo>();
// Get collection of cells.
SharedPtr<System::Xml::XmlNodeList> cells = row->SelectNodes(u"td");
for (const auto& cell : System::IterateOver(cells))
{
// Determine row span and colspan of the current cell.
SharedPtr<System::Xml::XmlAttribute> colSpanAttr = cell->get_Attributes()->idx_get(u"colspan");
SharedPtr<System::Xml::XmlAttribute> rowSpanAttr = cell->get_Attributes()->idx_get(u"rowspan");
int colSpan = colSpanAttr == nullptr ? 0 : System::Int32::Parse(colSpanAttr->get_Value());
int rowSpan = rowSpanAttr == nullptr ? 0 : System::Int32::Parse(rowSpanAttr->get_Value());
auto cellInf = MakeObject<WorkingWithTables::CellInfo>(colSpan, rowSpan);
rowInf->get_Cells()->Add(cellInf);
}
tableInf->get_Rows()->Add(rowInf);
}
mTables->Add(tableInf);
}
}
VisitorAction VisitCellStart(SharedPtr<Cell> cell) override
{
int tabIdx = mWordTables->IndexOf(cell->get_ParentRow()->get_ParentTable());
int rowIdx = cell->get_ParentRow()->get_ParentTable()->IndexOf(cell->get_ParentRow());
int cellIdx = cell->get_ParentRow()->IndexOf(cell);
int colSpan = 0;
int rowSpan = 0;
if (tabIdx < mTables->get_Count() && rowIdx < mTables->idx_get(tabIdx)->get_Rows()->get_Count() &&
cellIdx < mTables->idx_get(tabIdx)->get_Rows()->idx_get(rowIdx)->get_Cells()->get_Count())
{
colSpan = mTables->idx_get(tabIdx)->get_Rows()->idx_get(rowIdx)->get_Cells()->idx_get(cellIdx)->get_ColSpan();
rowSpan = mTables->idx_get(tabIdx)->get_Rows()->idx_get(rowIdx)->get_Cells()->idx_get(cellIdx)->get_RowSpan();
}
std::cout << tabIdx << "." << rowIdx << "." << cellIdx << " colspan=" << colSpan << "\t rowspan=" << rowSpan << std::endl;
return VisitorAction::Continue;
}
private:
SharedPtr<System::Collections::Generic::List<SharedPtr<WorkingWithTables::TableInfo>>> mTables;
SharedPtr<NodeCollection> mWordTables;
};

Skakel Om Na Horisontaal Saamgesmelte Selle

Soms is dit nie moontlik om te ontdek watter selle saamgesmelt word nie omdat sommige nuwer weergawes van Microsoft Word nie meer die samesmeltingsvlae gebruik wanneer selle horisontaal saamgesmelt word nie. Maar vir situasies waar selle horisontaal in’n sel saamgevoeg word deur hul breedte met behulp van samesmeltingsvlae, bied Aspose.Words die ConvertToHorizontallyMergedCells metode om selle te omskep. Hierdie metode verander eenvoudig die tabel en voeg nuwe selle by soos nodig.

Die volgende kode voorbeeld toon die bogenoemde metode in werking:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto doc = MakeObject<Document>(MyDir + u"Table with merged cells.docx");
SharedPtr<Table> table = doc->get_FirstSection()->get_Body()->get_Tables()->idx_get(0);
// Now merged cells have appropriate merge flags.
table->ConvertToHorizontallyMergedCells();