This article describes how to obtain edited document content from the client, process it and save it to the resultant document of some specified format.
In a nutshell, the core process of document editing, where a user types some text across the pages of the document, inserts images, makes some edits, removes words or paragraphs, or moves some document parts from one location to another, is performed in some 3rd party software with GUI outside of GroupDocs.Editor. This software may be, for example, but not limited to:
a web-based WYSIWYG HTML-editor, that is usually a pure client-side application, written in JavaScript and running in the browser. This may be, for example, a TinyMCE or CKEditor;
a desktop application;
a mobile application, running on Android or iOS.
The core requirement for this application is to be able to open, view and edit HTML content. GroupDocs.Editor on its side accepts various document formats (WordProcessing, Spreadsheet, Presentation, and many more) and prepares them for editing in external applications by converting them to the HTML markup and placing it in the EditableDocument container. So when calling the Editor.edit() method, the EditableDocument with the original content inside it is generated.
Then the user obtains this original content from the EditableDocument, pushes it to the external HTML-editor, makes edits, and when these edits are done, the user has the modified content. In the GroupDocs.Editor terminology, saving a document means obtaining the modified content and generating the document in the output format (WordProcessing, Spreadsheet, Presentation, and many more) from it. And this article explains how to do this.
In short, saving a document implies the next three steps:
Obtain the modified content from somewhere (HTML-editor or any other storage or method) and create an instance of EditableDocument from it. EditableDocument actually serves as an object-oriented wrapper of the document content.
Select a desired output format, into which the modified content should be saved, and optional parameters.
Save the modified content to the document of the previously chosen format by specified file path or into a specified stream using the Editor.save() method.
These three steps are explained in detail and with code samples below.
Obtaining the modified content
Different content editors provide the content in different forms. Some may return HTML markup as a string, while the external resources like stylesheet(s) and/or image(s) are located in some specific folder as files. Others may return both main content and resources as a collection of byte streams. Some HTML-editors may generate a single string, which already contains all HTML markup with resources baked into it using base64 encoding. There may be unlimited possibilities to do that, and thus the EditableDocument class has different class methods (factories), which obtain the modified content of the HTML document in different forms on input and according to this generate the EditableDocument instance:
from_file is designed for opening HTML-documents from disk — it obtains a path to a .html file (that contains HTML-markup) and a path to the corresponding resource folder that contains different resources, like stylesheets, images, font files, audio files and so on.
from_markup is designed for opening HTML-documents from memory — it obtains the HTML-markup as a string with resources baked into it.
from_markup_and_resource_folder is designed for opening HTML-documents from mixed storages — it obtains the HTML-markup as a string, but resources are obtained from a path to the corresponding resource folder, which, unlike the previous method, is mandatory (such a directory should exist).
Create and adjust saving options
When the EditableDocument instance with the modified content is created, it’s time to save it to the resultant document of some defined format, and GroupDocs.Editor needs to know this format. Like with load and edit options, every family format has its own save options class. These classes are listed below.
So, let’s say it is necessary to save the modified content to a document of DOCX format. DOCX is part of the WordProcessing family. So an instance of the WordProcessingSaveOptions class should be created, and the WordProcessingFormats.DOCX value should be specified in its constructor. Like this:
Also need to mention that the format of the input document with the original content and the format of the resultant document with the modified content may be different. For example, the original document can be in some WordProcessing format, while the output document can be TXT or PDF. Or the original document can be a PDF, while the output is DOCX. The same transitions are allowed between Spreadsheets and DSV (two-ways). But, of course, they are not allowed where formats are theoretically incompatible in their essence, like WordProcessing and Spreadsheet.
Saving modified content to the document
Finally, when the instance of the EditableDocument class with modified content inside is created, and the format of the resultant document is defined, it is possible to generate this resultant document using the Editor.save() method. This method has two overloads. These overloads differ only in the way the output document is specified: as a path, where the file should be created, or as a byte stream, into which the document content should be written. All other parameters are the same.
The 1st parameter — input_document — is an EditableDocument instance with the modified content inside, created on the 1st step.
The 2nd parameter is a stream, into which the resultant document of the defined format should be written, or a string, that represents a file path, where the resultant document of the defined format should be stored.
The 3rd parameter is an instance of some save options, which defines the format of the resultant document and additional adjustments, created on the 2nd step.
There is also a simplified overload that analyzes the file extension of the file_path argument and infers the default saving options automatically:
editor.save(input_document,file_path)
Complete code example
Because the WYSIWYG HTML-editor is not a part of GroupDocs.Editor, it is hard to provide a lightweight code example with fully functional editing. So in this sample the content will be edited programmatically, using the string replace method. The example loads a DOCX document, edits its content, and saves the modified content to several output formats — RTF, DOCM, and TXT.
importosfromgroupdocs.editorimportEditor,EditableDocument,Licensefromgroupdocs.editor.formatsimportWordProcessingFormatsfromgroupdocs.editor.optionsimportWordProcessingSaveOptions,TextSaveOptionsdefsave_document():# Optionally set a licenselicense_path=os.path.abspath("./GroupDocs.Editor.lic")ifos.path.exists(license_path):License().set_license(license_path)# Create the Editor by loading an input document in DOCX formatwithEditor("./sample-document.docx")aseditor:# Open the document for editing and obtain an EditableDocumentoriginal=editor.edit()# Get the original content as a stringoriginal_content=original.get_embedded_html()# Get the modified content by editing the original contentmodified_content=original_content.replace("Title of the document","Title of the edited document")# Create an EditableDocument from the modified contentmodified=EditableDocument.from_markup(modified_content)# Save the modified content to several output formatseditor.save(modified,"./edited-document.rtf",WordProcessingSaveOptions(WordProcessingFormats.RTF))editor.save(modified,"./edited-document.docm",WordProcessingSaveOptions(WordProcessingFormats.DOCM))editor.save(modified,"./edited-document.txt",TextSaveOptions())# Release the EditableDocument instancesoriginal.dispose()modified.dispose()if__name__=="__main__":save_document()
sample-document.docx is the sample file used in this example. Click here to download it.
In this example, three different save options are created and three different Editor.save() calls are made for saving the modified content to the RTF, DOCM, and TXT formats.
Was this page helpful?
Any additional feedback you'd like to share with us?
Please tell us how we can improve this page.
Thank you for your feedback!
We value your opinion. Your feedback will help us improve our documentation.