Cannot create StructuredDocumentTag with TOC using Aspose.Words.C++

,

keywords for find this issue
#TableOfContent #StructedDocumentTag #DocPartObj #InsertTableOfContents #FieldTOC

Hello! I am trying to make a table of contents as it is done for the MS Word client. When I do it manually, it turns out like this:

word1.docx (13.4 KB)

It turns out that this is the table of contents. But this is different from what happens if you call the builder->Insert Table Of Contents function. After this function, the TOC field is inserted, which contains the correct table of contents, but you cannot put your title there inside “group”, as it is done in image1, and there is no border, and the background when hovering the cursor (in word1.docx all its features works). The с++ code and the resulting output doc:

auto doc = MakeObject<Words::Document>();
auto builder = MakeObject<Words::DocumentBuilder>(doc);

builder->InsertTableOfContents(u"\\o \"1-3\" \\h");
builder->InsertBreak(Words::BreakType::ParagraphBreak);
builder->get_ParagraphFormat()->set_StyleIdentifier(StyleIdentifier::Heading1);
builder->Write(u"SomeChapter");

doc->UpdateFields();
doc->Save(u"D:\\TMP\\word2.docx");

word2.docx (23.8 KB)

Then i looked at the structure of the document word1.docx using showcases, he showed me the following:

I’m reasoning - it turns out you need to create a SctructedDocumentTag with child paragraphs, just like it’s done in image2. it remains to understand what type of SdtType this SctructedDocumentTag is. Running this with my word1.docx:

auto doc = MakeObject<Words::Document>(u"D:\\TMP\\word1.docx");
SharedPtr<NodeCollection> sdtCollection = doc->GetChildNodes(NodeType::StructuredDocumentTag, true);
auto sdt = System::DynamicCast<StructuredDocumentTag>(sdtCollection->idx_get(0));
cerr << (int)sdt->get_SdtType() << endl;

i got ‘8’. its DocPartObj:

Next, I’m trying to run this code to create a table of contents as in word1.docx using Aspose.Words:

auto doc = MakeObject<Words::Document>();
auto builder = MakeObject<DocumentBuilder>(doc);

auto sdt = MakeObject<StructuredDocumentTag>(doc, SdtType::DocPartObj, MarkupLevel::Inline);

System::SharedPtr<Paragraph> para1 = System::MakeObject<Paragraph>(doc);
para1->AppendChild(MakeObject<Run>(doc, u"TableOfContents"));
sdt->AppendChild(para1);

System::SharedPtr<Paragraph> para2 = System::MakeObject<Paragraph>(doc);
para2->AppendField(FieldType::FieldTOC, true);
sdt->AppendChild(para2);

builder->InsertNode(sdt);

doc->Save(u"D:\\TMP\\word3.docx");

but i got exception while creating sdt: System::ArgumentException: Creation of such SdtType is not allowed.

If the creation of this type is not allowed, is there a possibility to do as in word1.docx ?

@vavp Unfortunately, you are right, Aspose.Words at the moment does not allow creating DocPartObj SDT. We will consider providing an API to insert TOC building block, just like MS Word does. I have logged this feature request as WORDSNET-24147. We will keep you informed and let you know once it is resolved.
For now, you can insert such building block using MS Word into a document, and then copy it into your target document in your code. For example see the following code:
[C#]

Document tocDoc = new Document(@"C:\Temp\in.docx");
StructuredDocumentTag sdtToc = (StructuredDocumentTag)tocDoc.GetChild(NodeType.StructuredDocumentTag, 0, true);

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
StructuredDocumentTag targetSdt = (StructuredDocumentTag)doc.ImportNode(sdtToc, true, ImportFormatMode.UseDestinationStyles);
builder.CurrentParagraph.ParentNode.InsertBefore(targetSdt, builder.CurrentParagraph);
builder.Writeln();
builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Heading1;
builder.Write("Heading");
doc.Save(@"C:\Temp\out.docx");

[C++]

auto tocDoc = System::MakeObject<Document>(u"C:\\Temp\\in.docx");
auto sdtToc = System::DynamicCast<StructuredDocumentTag>(tocDoc->GetChild(NodeType::StructuredDocumentTag, 0, true));

auto doc = System::MakeObject<Document>();
auto builder = System::MakeObject<DocumentBuilder>(doc);
auto targetSdt = System::DynamicCast<StructuredDocumentTag>(doc->ImportNode(sdtToc, true, ImportFormatMode::UseDestinationStyles));
builder->get_CurrentParagraph()->get_ParentNode()->InsertBefore(targetSdt, builder->get_CurrentParagraph());
builder->Writeln();
builder->get_ParagraphFormat()->set_StyleIdentifier(StyleIdentifier::Heading1);
builder->Write(u"Heading");
doc->Save(u"C:\\Temp\\out.docx");

Ans here is in.docx this is a simple document with SDT you need to insert: in.docx (13.9 KB)

1 Like