How to copy specific pages of Word document - c#

I have a word document which contains multiple pages and i want to copy some pages into new word document using OpenXml SDK. I did some web search and got below code which reads entire document and copies into new one
string documentURL = filelocation;
byte[] docAsArray = File.ReadAllBytes(documentURL);
using (MemoryStream stream = new MemoryStream())
{
stream.Write(docAsArray, 0, docAsArray.Length); // THIS performs doc copy
using (DocumentFormat.OpenXml.Packaging.WordprocessingDocument doc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open(stream, true))
{
// perform content control substitution here, making sure to call .Save()
// on any documents Part's changed.
}
File.WriteAllBytes(outputSplitDocpath, stream.ToArray());
}
Now, in the above code how can i read just specific pages and copy into new one? Please help with suggestions. Thanks

Unless a manual page break has been used to generate every page in the document, what you want to do is not possible.
Automatic page breaks are generated by Word, at run-time, when the document is open in the Word application. The actual placement of a page break is completely dynamic, based on the editing being done and is recalculated "all the time" during editing.
This information is not reliably saved in the document when the document is closed. One reason for this is because the document could lay out differently when opened on a different machine, or when a different printer (driver) is selected.
So it's not possible to work with individual pages using the Office Open XML file format unless there's some way each page can be recognized, such as a manual page break.

Use Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
instead of OpenXML
//dummy value to satisfy params
object oMissing = System.Reflection.Missing.Value;
//copy specific page/s
object what = WdGoToItem.wdGoToPage;
object which = WdGoToDirection.wdGoToFirst;
object count1 = 1;
Range startRange = word.Selection.GoTo(ref what, ref which, ref count1, ref oMissing);
object count2 = (int)count + 1;
Range endRange = word.Selection.GoTo(ref what, ref which, ref count2, ref oMissing);
endRange.SetRange(startRange.Start, endRange.End - 1);
endRange.Select();
word.Selection.Copy();
//save...

Related

In word 365 where can I find the template variables to place them on the page?

We have an existing legacy system where I'm able to download existing templates, update them and save them as documents with my edits. Here is a portion of the code.
#region Open existing Template and write something to it.
object missing = Type.Missing;
Word.Application app = new Word.Application();
Word.Document doc = app.Documents.Open(#"C:\\test395310.dot", ref missing, true);
doc.Activate();
doc.Variables["CASE PLAN_PLAN_STATUS"].Value = "asdf1";
doc.Variables["CASE PLAN_PROGRAM"].Value = "asdf2";
doc.Fields.Update();
#endregion
Using similar logic I'm attempting to create a new word template with 2 variables.
private static void CreateTemplate()
{
//have it open word and create a template with fields from gen
object missing = Type.Missing;
Word.Application app = new Word.Application();
Word.Document doc = app.Documents.Add(ref missing, ref missing, true);
doc.Activate();
doc.Variables.Add("CASE PLAN_PLAN_STATUS", "XXXXX");
doc.Variables.Add("ANOTHER ONE", "XXXX");
doc.Fields.Update();
doc.SaveAs2(#"C:\\newTemplate.dot");
doc.Close();
app.Quit();
}
The document is getting created, however in word I cannot find either variable. My goal is to open word and placement in the template with formatting. ie
Plan Status: <<CASE PLAN_PLAN_STATUS>>
If I click insert/Explore Quick Parts/field, I can see various options, but my two variables aren't there. Anyone know where else to look? Or a better approach?
Within your template, you can use DocVariable fields.
https://support.microsoft.com/en-us/office/field-codes-docvariable-field-32a81e22-c5c1-4b16-8097-f0de851db67c?ui=en-US&rs=en-US&ad=US
It would look like { DocVariable Case_Plan_Plan_Status } with field codes revealed.
Unlike Document Properties, Document Variables can only be created, modified, or deleted using vba.
There are no built-in Document Variables. There is no tool built into the user interface for seeing what is available among variables.
I do know of several good Add-Ins for manipulating them in the user interface.
One is Chris Woodman's old Keyboard Shortcut Organizer.
http://addbalance.com/word/download.htm#ChrisWoodman
This one lets you view, create, edit and delete variables from within Word but does not create a DocVariable field, leaving that for you to do.
Another is Graham Mayor's or Greg Maxey's utility.
http://gregmaxey.com/word_tip_pages/cc_var_bm_doc_prop_tools_addin.html
or
http://www.gmayor.com/BookmarkandVariableEditor.htm
Both of these last two can add a DocVariable Field to your document after you select the variable from a list.

C#: print out Word document without saving it in advance document.PrintOut()

I want to print out a Word document without saving it in advance. Is this possible?
//I created an instance for word app
Microsoft.Office.Interop.Word.Application winword = new Microsoft.Office.Interop.Word.Application();
//I created a Word document (including pararaphs and tables):
Microsoft.Office.Interop.Word.Document document = winword.Documents.Add(ref missing, ref missing, ref missing, ref missing);
//I can print the document, if I save it before. But I want to print it without saving the word document.
document.SaveAs2(#"C:\User\\Desktop\Test");
document.PrintOut()
//Export of the document as pdf-file.
document.ExportAsFixedFormat(label24.Text + "Document" + textBox13.Text, WdExportFormat.wdExportFormatPDF, true);
If the problem is that the document is closing before the print job has completed, then the best approach is to turn off background printing, at least for the duration of code execution.
winword.Options.PrintBackground = false;
Background printing was introduced in order to allow the user to continue working while a print job was processing. This is fine for the user, but a problem for code such as that in the question.

Selection.InsertFile fails with "disk is full" error message

With c# and Interop Word I am trying to merge all the files in a specified directory into a new document. My code loops through a list of file names and uses "InsertFile" to add each one to a Selection.
There are a lot of files, and the process is failing after a while. The error message reads:
The disk is full. Free some space on this drive, or save the document on another disk.
Try one or more of the following:
Close any unneeded documents, programs, and windows.
Save the document on another disk."
At the point where the InsertFile fails the selection is using about 7MB. My disk has 300GB of free space and the machine has 32GB of RAM.
The files I am saving do not have any graphics or Math in them.
What am I doing wrong? The exception is getting thrown on the InsertFile line inside the foreach loop (below).
The code follows in a second. Please note that I start from a winword instance, which is a member of a class called PrintObj. Also, please note that this code works fine if I use it with a small number of files, like 100-200).
Document mergeDoc = PrintObj.WinWord.Documents.Add(ref missing, ref missing,
ref missing, ref missing);
mergeDoc.PageSetup.LeftMargin = globalPrintObj.WinWord.InchesToPoints(0.5f);
mergeDoc.PageSetup.RightMargin =
PrintObj.WinWord.InchesToPoints(0.5f);
string[] filePaths = Directory.GetFiles(directoryPath, "*.docx");
string[] documentsToMerge = filePaths;
Array.Sort(documentsToMerge);
// Make a Word selection object.
Selection selection = PrintObj.WinWord.Selection;
//A counter that signals that we shoudn't insert a page break at the end of
document.
int breakStop = 0;
//Count the number of documents to insert;
int documentCount = documentsToMerge.Length;
// Loop thru each of the Word documents
foreach (string file in documentsToMerge)
{
breakStop++;
// Insert the files to our template
selection.InsertFile(file, ref missing, ref missing, ref missing,
ref missing);
if (breakStop != documentCount)
{
selection.InsertBreak(ref pageBreak);
}
}
Directory.CreateDirectory(directoryPath);
//Save the document
obj wordFileName = fileNameWithExtension;
mergeDoc.SaveAs2(ref wordFileName);
Could you check the path with the name of the files?
sometime ago i remember got that error of Disk full for the 255 characters problem, maybe one of those files has a too longe path
https://support.code42.com/CrashPlan/4/Troubleshooting/Windows_file_paths_longer_than_255_characters
try save the files in a different directory, like C:\YourFolder
Eventually I gave up on the MS assemblies and used the Xceed.Words.NET to solve this, which works. When using the Selection object the process always hung after about 840 insert docs (it was always the same exact number of insert docs), which was a problem because I needed to insert more than 1200 files. The final doc currently has just over 15,706,000 characters and over 11,700 pages, and is just over 4MB.
It seems to me that this is a flaw in the Interop Word Document Class because appending documents is a pretty common use case.
((Note added a couple of weeks later - had a chance to go back and try adding a counter every time an insert is done and then
if (Counter % 100 == 0)
{
mergeDoc.UndoClear();
}
This worked. Thank you to CM who suggested it.

Create, insert text and save a Word doc in C#

I've found loads of useful documentation around creating an instance of a word doc, inserting all manner of text and formatting but cannot find anywhere something to save a document that hasnt already been created and opened programmatically.
Essentially I want to create a docx file and fill it with text from a rich text box. Using code Ive found at How to Insert text in the end of the document I am able to achieve this if I first create a document. But despite suggestions of using _document.SaveAs() (which doesnt exist - version diff i guess) or .Save() supposedly prompting with a SaveAs dialogue if the file doesnt already exist, I always get a type mismatch error. So this is the working code if i pre-create the file to use:
OpenFileDialog SDO = new OpenFileDialog();
SDO.ShowDialog();
Microsoft.Office.Interop.Word._Application oWord;
object oMissing = Type.Missing;
oWord = new Microsoft.Office.Interop.Word.Application();
oWord.Visible = false;
oWord.Documents.Open(SDO.FileName);
oWord.Selection.TypeText(richTextBox1.Text);
oWord.ActiveDocument.Save();
oWord.Quit();
Now one would assume that removing the lines for the OpenFileDialogue Documents.Open would go some way to saving a new file created in C#, however even with:
Microsoft.Office.Interop.Word._Application oWord;
object oMissing = Type.Missing;
oWord = new Microsoft.Office.Interop.Word.Application();
oWord.Visible = false;
SaveFileDialog SD = new SaveFileDialog();
SD.Filter = "Word File |*.docx";
SD.Title = "Save File";
SD.ShowDialog();
oWord.Documents.Save(SD.FileName,WdNewDocumentType.wdNewXMLDocument);
oWord.Selection.TypeText(richTextBox1.Text);
oWord.ActiveDocument.Save();
oWord.Quit();
Other examples ive seen open the document so that you can save it yourself but i need it saving without any human intervention other than choosing a filename.
Any help appreciated, also the option of third party dlls like spire and gem are precluded so not an option :(
If anyone has a simple example of creating and saving a word doc that didnt exist before the program ran id be much obliged.
The Microsoft MSDN documentation has tons of useful guides and examples.
You are going to want to include:
using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Tools.Word;
Then declare your application:
Word.Application app = new Word.Application();
Declare your new document:
Word.Document doc = app.Documents.Add();
Add text to your documnet
There are two ways to save these documents:
Programmatically
Using a save file dialog box
This is the way I do it.
app = new Word.Application();
object oMissing = System.Reflection.Missing.Value;
Word._Document oDoc = app.Documents.Add(ref oMissing, ref oMissing,
ref oMissing, ref oMissing);
.....
app.ActiveDocument.SaveAs2(fileName);
Where filename is my desired file name. When I was originally doing this, I discovered that there were a lot of undocumented (and therefore unsupported) functions. SaveAs2 is one of them! But it does work.

How to remove the 'Read only recommended' option in a Word document using c#?

I'm working in an application that interact with Word. We import documents in our database then allow the user to modify those documents using Microsoft Word via NetOffice.WordApi.
We are having some issues when the document is marked as read-only, everytime is opened, we get a 'Save As' word dialog that gives you the option of creating a temporal copy of the document to allow you to make changes in the document.
My question is as follow: How can remove the read-only word mark of the document and re-save the document without the mark? I can remove the option manually from word following the instructions in the link below, but I want to automatise that process by code.
The author would like you to open this as read-only
** PLEASE BEFORE ANSWER NOTICE THE FOLLOWING: It's not the read-only property in the file at windows level, it's not an issue with the windows permision attibute. The file attributes are NOT Read-only the property is inside the word document. So changing the windows file permision attributes by code doesn't work, actually the files are not read-only when you check the file properties in windows, it's a word attribute which means the author marked the document as read-only when he saved it and will stop you to modify the file using word (file can be changed using a different software, it just read-only for word). Please don't sent me links about how to change permissions in windows at that's not the case, check the link for more info. **
Many thanks for your time.
The option you want to set is the Document.ReadOnlyRecommended property of the Word document.
When you open a Word document, you can actually set the ReadOnly property with the third argument in the Document.Open method. That argument won't, however, override the read-only recommended setting on a saved document. So if your document is saved with read-only recommended option, it will be opened as read-only when calling Document.Open.
So I think that you have two option:
Option 1
Set the Document.ReadOnlyRecommended to false before the Document is saved for the first time, similar to this
objDoc.ReadOnlyRecommended = false;
Option 2
If the document already is set to read-only recommended, you need to save the document as a new file with the Document.ReadOnlyRecommended property set to false using the Document.SaveAs2 method.
Your code might look like this:
object missing = System.Reflection.Missing.Value;
object readOnly = false;
object fileName = #"C:\User\MyFile.docx";
object newFileName = #"C:\User\MyNewFile.docx";
var objApp = new Application();
var objDoc = objApp.Documents.Open(ref fileName, ref missing, ref readOnly);
if (objDoc.ReadOnlyRecommended)
{
objDoc.SaveAs2(ref newFileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref readOnly);
}
objDoc.Close();
objApp.Quit();

Categories