How to insert Visio file into DOCX

Hi guy,
In my DOCX(in.docx), there is a paragraph whose text is ‘Insert_Visio_Here’. I want to replace it with the real Visio file(my.vsdx) using your aspose.words. how to do that?

@space_chang You can insert a Visio file into MS Word using Aspose.Words as an OLE object. Please see our documentation for more information:
https://docs.aspose.com/words/net/working-with-ole-objects/

@alexey.noskov, Yes, i have saw this section. but my purpose is to replace the existing text in DOCX with a Visio file instead of insert it anywhere. In my DOCX , there will be serveral parts that are marked with specific text and should be repalced with Visio file. for example, replacing 'Insert_Visio1_here ’ with visio1.vsdx, replacing 'Insert_Visio2_here ’ with visio2.vsdx, …

@space_chang Could you please attach your sample input and expected output documents? This will help us better to understand your requirements.
Is the problem is with inserting Visio file at placeholder or with inserting Visio file at all?

@alexey.noskov, I attached the sample documents i wanted. the the three texts in source document (in.docx)need to be replaced with three different Visio file in target document(out.docx).
in.docx (18.5 KB)

out.docx (56.3 KB)

@space_chang Thank you for additional information. You can achieve this using the following code:

// Map of placeholders to objects
Dictionary<string, string> placeholderToObjectMap = new Dictionary<string, string>();
placeholderToObjectMap.Add("Chapter1_picture", @"C:\Temp\Microsoft_Visio_Drawing.vsdx");
placeholderToObjectMap.Add("Chapter11_picture", @"C:\Temp\Microsoft_Visio_Drawing1.vsdx");
placeholderToObjectMap.Add("Chapter12_picture", @"C:\Temp\Microsoft_Visio_Drawing2.vsdx");

// open template
Document doc = new Document(@"C:\Temp\in.docx");
DocumentBuilder builder = new DocumentBuilder(doc);

// Replace placeholders with themselves to make them to be represented as a single run.
FindReplaceOptions opt = new FindReplaceOptions();
opt.UseSubstitutions = true;
Regex placeholderRegex = new Regex(string.Join("|", placeholderToObjectMap.Select(x => Regex.Escape(x.Key))));
doc.Range.Replace(placeholderRegex, "$0", opt);

// Loop throug runs in the document and replace placeholders with Visio objects.
foreach (Run r in doc.GetChildNodes(NodeType.Run, true))
{
    if (placeholderToObjectMap.ContainsKey(r.Text))
    {
        builder.MoveTo(r);
        builder.InsertOleObject(placeholderToObjectMap[r.Text], false, true, null);
        r.Text = "";
    }
}

doc.Save(@"C:\Temp\out.docx");

@alexey.noskov, thank you for the guide. could you provide python-based sample code? It seems that there is no definition for ‘FindReplaceOptions’ in your python-based library.

@space_chang Sure, here is Python version of the code:

# Map of placeholders to objects
placeholder_to_object_map  = {
    "Chapter1_picture" : "C:\\Temp\\Microsoft_Visio_Drawing.vsdx",
    "Chapter11_picture" : "C:\\Temp\\Microsoft_Visio_Drawing1.vsdx",
    "Chapter12_picture" : "C:\\Temp\\Microsoft_Visio_Drawing2.vsdx"
}

# open template
doc = aw.Document("C:\\Temp\\in.docx")
builder = aw.DocumentBuilder(doc)

# Replace placeholders with themselves to make them to be represented as a single run.
opt = aw.replacing.FindReplaceOptions()
opt.use_substitutions = True
placeholderRegex = "|".join(placeholder_to_object_map)
doc.range.replace_regex(placeholderRegex, "$0", opt)

# Loop throug runs in the document and replace placeholders with Visio objects.
for r in doc.get_child_nodes(aw.NodeType.RUN, True) :
    run = r.as_run()
    if run.text in placeholder_to_object_map :
        builder.move_to(run)
        builder.insert_ole_object(placeholder_to_object_map[run.text], False, True, None)
        run.text = ""

doc.save("C:\\Temp\\out.docx")

I provided C# version of the code because you have specified words-net tag of the topic. I changed the tag to words-python to avoid further confusion.

@alexey.noskov, sorry for my improper tag and it works well now. thanks for your support. I have a puzzle about your code, what is purpose to replace the placeholders?

@space_chang

Text in MS Word is represented by Run nodes, the placeholder might be represented by several Run nodes, for example if document has been edited or part of placeholder was formatted differently than other part. After replacing placeholder with itself the whole placeholder will be represented as a single Run node, and it will be easy to find it and move DocumentBuilder cursor to it.

@alexey.noskov, thank you very much for the explanation and i get it.

1 Like

@alexey.noskov Currently, i want to show the visio figure in docx directly instead of only showing file icon. I disabled the ’ as_icon’ in your api as

builder.insert_ole_object(placeholder_to_object_map[run.text], False, False, None)

but the figure in docx is shown as

Please help to check it.

@space_chang This is an expected behavior. You pass None as OLE object presentation, so Aspose.Words uses default image. To show preview of Visio object you should render it to image and pass this image as OLE object presentation into insert_ole_object method. Unfortunately, rendering of Visio objects is out of Aspose.Words scope. You can use Aspose.Diagram to render Visio objects:
https://docs.aspose.com/diagram/python-net/convert-visio-to-image/

@alexey.noskov what i wanted is like the function of ‘inserting object’ in MS Office without ico. it is editable figure instead of static image. that is to say when i open attached visio file, edit it and save it, the figure in docx will be refershed automatically.

@space_chang Visual representation of Visio or any other object in MS Word document are metafile images. When you open OLE object for editing it is opened by the corresponding consumer application, after saving MS Word with assistance of consumer application generates new metafile for visual representation of the OLE object.

@alexey.noskov thanks for your explanation. If it is, how can i use aspose.words to meet this requirement. I think it is a common funcationality in MS Office when inserting visio diagram.

@space_chang To achieve what you need you should render your Visio diagram to metafile image and use this image as OLE object presentation upon inserting it into the document.

@alexey.noskov thanks for your guide and i will follow it to try the solution.

1 Like

@alexey.noskov I tried your aspose.diagram to convert vsdx into emf. and it can be inerted into docx smoothly. but the figure size(width&height) is so large. how to adapt the presentation figure to the actual size of docx page?

@space_chang You can change size of the insert OLE object shape. For example see the following simple code:

doc = aw.Document()
builder = aw.DocumentBuilder(doc)

with open("C:\\Temp\\src.emf", "rb") as presentation_stream :
    ole_shape = builder.insert_ole_object("C:\\Temp\\src.docx", False, False, presentation_stream)
    # change OLE object shape size as required
    # by default lock aspect ratio option is enabled so the shape is resized proportionaly.
    # you can disable this option to chnage width and height independently
    ole_shape.aspect_ratio_locked = False
    ole_shape.width = 100
    ole_shape.height = 100

doc.save("C:\\Temp\\out.docx")