i`m using function below to fill properly data in doc.file by bookmarks and it works good.
public void findAndReplace(Word.Document doc, object bookmark, object replaceWith)
{
Word.Range rng = doc.Bookmarks.get_Item(ref bookmark).Range;
rng.Text = replaceWith.ToString();
object oRng = rng;
doc.Bookmarks.Add(bookmark.ToString(), ref oRng);
}
I`ve got problem with setting values of choice-fields in word file.
My questions is, is it even possible to set this kind of data from my c# application ? There is any method to generate Selected or unselected fields like for example in point 21 in link below or only set its value ?
http://www.fotosik.pl/pokaz_obrazek/c2409113d79afeba.html
And last question is it possible and reasonable to generate whole report from doc file ?
I`m looking for some solution which helps to generate completely my declaration by c#.
Yes that is possible by programmatically adding Content Controls.
This is how you would add a Check Box Content Control:
this.Paragraphs[1].Range.InsertParagraphBefore();
this.Paragraphs[1].Range.Select();
Microsoft.Office.Tools.Word.ContentControl checkBoxControl1 =
this.Controls.AddContentControl("checkBoxControl1", Word.WdContentControlType.wdContentControlCheckBox);
checkBoxControl1.Checked = true;
You can generate entire documents from c#. I would suggest this tutorial from MSDN about creating templates by using content controls.
Related
I have the requirement to create an Bitmap Object from a Excel Path inside a ms-word document, and I can't seem to find a way to do it in one step.
The current solution is the following.
Create a Field Object
Unlink the Field Object
Like this:
Dim fld As Field
Set fld = Selection.Fields.Add(Selection.Range, WdFieldType.wdFieldLink, "Excel.Sheet.12 ""[Path to Xlsx]"" ""[Sheet+Range]"" \b", False)
fld.Update
fld.Unlink
\b says the field should represented as a Bitmap object.
With fld.Unlink I am dropping the link and the Bitmap stays.
Is there a way to directly create the Bitmap Object (InlineShape) without the field approach?
I tried to record a macro in ms-word to see how ms-word is doing it but saddly it only gives:
Selection.PasteSpecial Link:=False, DataType:=wdPasteBitmap, Placement:= wdInLine, DisplayAsIcon:=False
If possible I would like to avoid working with Clipboard and PasteSpecial.
Edit:
Since the given answer has shown me that my question wasn't as clear as I hoped it to be.
So first of all, the only Information I currently have are
The path to an XLSX file
The Sheet and Range of said XLSX File
eg.
C:\test\myWorkbook.xlsx
Sheet1!A1:D10
Thats all the Information I have.
With this Information I need to programatically create a Bitmap inside my ms-word document.
As shown above I already have a solution which does exactly this, by doing a LINK to the said XLSX file and after it got updated dropping that link to only have the Bitmap left.
A Bitmap is staying here because of the \b flag which tells the LINK to produce a Bitmap, instead of a RTF/HTML.
My question now is, if there is another way I am currently doing it.
The current answer, does indeed insert a Bitmap into my ms-word document, but where do I get the Bitmap from, as the answer isn't aware of the fact that I need an image of an excel workbook? As I said earlier, I only have limited information and no Bitmap.
What I want to achieve can be done without programatically by using the Paste Special functionality
https://support.office.com/en-us/article/paste-special-e03db6c7-8295-4529-957d-16ac8a778719
Open Xlsx/Docx
Copy Cells from Xlsx
Go to Docx
Use Paste Special
Select Bitmap
Hit OK
The output you receive in your Docx is what I desire to make programatically, without Clipboard and Paste Special and with a, if possible, better solution than I currently have.
You can use the following code:
string fileName = "c://msdn.bmp"; //the picture file to be inserted
Object oMissed = doc.Paragraphs[2].Range; //the position you want to insert
Object oLinkToFile = false; //default
Object oSaveWithDocument = true;//default
doc.InlineShapes.AddPicture(fieldName, ref oLinkToFile, ref oSaveWithDocument, ref oMissed);
See insert a picture into a word document using c#? for more information.
I have a Word document, letter.docx, that is a letter I intend to mail to hundreds of people for a party. The letter is already composed and has been formatted in its own special way with varying type sizes and fonts. It's set and ready to go, with placeholders where I have to fill out variables that change like Name, Address, phone number, etc.
Now, I would like to write a C# program where a user can type in variable things like Name, Address, etc., into a form, hit a button, and produce letter.docx with the right information filled in at the right places.
I understand Word has features that allow you do this, but I really want to do this in C#.
Of course you can do it. Use Microsoft.Office.Interop.Word reference in your project.
First bookmark all the fields you want to be updated in the document from 'insert' tab (eg. NameField is bookmarked with tag 'name_field'). Then, in your C# code add the following:
Microsoft.Office.Interop.Word.Application wordApp = null;
wordApp = new Microsoft.Office.Interop.Word.Application();
wordApp.Visible = true;
Document wordDoc = wordApp.Documents.Open(#"C:\test.docx");
Bookmark bkm = wordDoc.Bookmarks["name_field"];
Microsoft.Office.Interop.Word.Range rng = bkm.Range;
rng.Text = "Adams Laura"; //Get value from any where
Remember to properly save & close the document.(You can see this)
I don't know of anything built into the language, but the example here seems to do exactly what you want.
If you can provide specific examples of what you want to do (are the placeholders Fields? specifically name bits of text?), I can probably give you a more refined answer that directly targets your problem.
Word Provides COM objects that one can make use of in C#
Add a reference to the Microsoft office interop under the COM tab in the add reference dialog
Also, see this question:
Filling in FIelds in work using C#
I had a situation where I needed to fill out some MS Word forms, so I used something similar to the following code (make sure you reference Microsoft.Office.Interop.Word; I used version 14, but you should adjust it to your own scenario):
// FormData is a custom container type that holds data... you'll have your own.
public static void FillOutForm(FormData data)
{
var app = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc = null;
try
{
var filePath = "Your file path.";
doc = app.Documents.Add(filePath);
doc.Activate();
// Loop over the form fields and fill them out.
foreach(Microsoft.Office.Interop.Word.FormField field in doc.FormFields)
{
switch (field.Name)
{
// Text field case.
case "textField1":
field.Range.Text = data.SomeText;
break;
// Check box case.
case "checkBox1":
field.CheckBox.Value = data.IsSomethingTrue;
break;
default:
// Throw an error or do nothing.
break;
}
}
// Save a copy.
var newFilePath = "Your new file path.";
doc.SaveAs2(newFilePath);
}
catch (Exception e)
{
// Perform your error logging and handling here.
}
finally
{
// Make sure you close things out.
// I tend not to save over the original form, so I wouldn't save
// changes to it -- hence the option I chose here.
doc.Close(
Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges);
app.Quit();
}
}
As you can see, it's really not that hard at all. There are some other options on forms, so you'll have to research them, but the most general ones, the check box and the text box, are the ones I demonstrated here. If you didn't create a form, I suggest going through and making sure that you know all the fields, as that's what you'll need for this.
I wrote a utility for another team that recursively goes through folders and converts the Word docs found to PDF by using Word Interop with C#.
The problem we're having is that the documents were created with date fields that update to today's date before they get saved out. I found a method to disable updating fields before printing, but I need to prevent the fields from updating on open.
Is that possible? I'd like to do the fix in C#, but if I have to do a Word macro, I can.
As described in Microsoft's endless maze of documentation you can lock the field code. For example in VBA if I have a single date field in the body in the form of
{DATE \# "M/d/yyyy h:mm:ss am/pm" \* MERGEFORMAT }
I can run
ActiveDocument.Fields(1).Locked = True
Then if I make a change to the document, save, then re-open, the field code will not update.
Example using c# Office Interop:
Word.Application wordApp = new Word.Application();
Word.Document wordDoc = wordApp.ActiveDocument;
wordDoc.Fields.Locked = 1; //its apparently an int32 rather than a bool
You can place the code in the DocumentOpen event. I'm assuming you have an add-in which subscribes to the event. If not, clarify, as that can be a battle on its own.
EDIT: In my testing, locking fields in this manner locks them across all StoryRanges, so there is no need to get the field instances in headers, footers, footnotes, textboxes, ..., etc. This is a surprising treat.
Well, I didn't find a way to do it with Interop, but my company did buy Aspose.Words and I wrote a utility to convert the Word docs to TIFF images. The Aspose tool won't update fields unless you explicitly tell it to. Here's a sample of the code I used with Aspose. Keep in mind, I had a requirement to convert the Word docs to single page TIFF images and I hard-coded many of the options because it was just a utility for myself on this project.
private static bool ConvertWordToTiff(string inputFilePath, string outputFilePath)
{
try
{
Document doc = new Document(inputFilePath);
for (int i = 0; i < doc.PageCount; i++)
{
ImageSaveOptions options = new ImageSaveOptions(SaveFormat.Tiff);
options.PageIndex = i;
options.PageCount = 1;
options.TiffCompression = TiffCompression.Lzw;
options.Resolution = 200;
options.ImageColorMode = ImageColorMode.BlackAndWhite;
var extension = Path.GetExtension(outputFilePath);
var pageNum = String.Format("-{0:000}", (i+1));
var outputPageFilePath = outputFilePath.Replace(extension, pageNum + extension);
doc.Save(outputPageFilePath, options);
}
return true;
}
catch (Exception ex)
{
LogError(ex);
return false;
}
}
I think a new question on SO is appropriate then, because this will require XML processing rather than just Office Interop. If you have both .doc and .docx file types to convert, you might require two separate solutions: one for WordML (Word 2003 XML format), and another for OpenXML (Word 2007/2010/2013 XML format), since you cannot open the old file format and save as the new without the fields updating.
Inspecting the OOXML of a locked field shows us this w:fldLock="1" attribute. This can be inserted using appropriate XML processing against the document, such as through the OOXML SDK, or through a standard XSLT transform.
Might be helpful: this how-do-i-unlock-a-content-control-using-the-openxml-sdk-in-a-word-2010-document question might be similar situation but for Content Controls. You may be able to apply the same solution to Fields, if the the Lock and LockingValues types apply the same way to fields. I am not certain of this however.
To give more confidence that this is the way to do it, see example of this vendor's solution for the problem. If you need to develop this in-house, then openxmldeveloper.org is a good place to start - look for Eric White's examples for manipulating fields such as this.
While I doubt it, if I open up a word document using OpenXML sdk in C# and add some info, is there any way for me to see if it still fits one page?
If it doesn't I wan't to reduce font size on specific items I added until it fits.
I could write this algorithm if I had the current size in relation to page size with margins and all that.
I ran across this example on another site, don't know if it'll work in your case, as it requires the Office PIA...
var app = new Word.Application();
var doc = app.Documents.Open("path/to/file");
doc.Repaginate()
var pageNumber = doc.BuiltInDocumentProperties("Number of Pages").Value as int;
I'm trying to modify some CustomDocumentProperties for a .docx document. I've been able to read the current value and modify it, but when I save the document the changes to the custom fields are lost.
I have the following method within a DocAccessor class (which serves as an interface for my doc files):
void SetInfo(string key, string val) {
object custom_properties = current_doc.CustomDocumentProperties;
Type custom_properties_type = custom_properties.GetType();
custom_properties_type.InvokeMember("Item", BindingFlags.Default | BindingFlags.SetProperty, null, custom_properties, new object[] { key, val });
}
elsewhere I call:
doc_accessor.GetInfo("Number") //returns 5
doc_accessor.SetInfo("Number", "6");
doc_accessor.GetInfo("Number") //returns 6
doc_accessor.SaveAndClose();
doc_accessor.Open(); //it retains the path, so I don't need to respecify
doc_accessor.GetInfo("Number") //returns 5
My doc_accessor.SaveAndClose() function is working correctly as I modified the path to save to a different location and it did... but without writing the modified CustomDocumentProperties. This makes it seem as if there's a commit step of sorts that I'm missing, but shouldn't current_doc.Save() handle that?
http://support.microsoft.com/kb/195425
http://msdn.microsoft.com/en-us/library/y1xatbkd(VS.80).aspx
i dunno if either of these will help.
but that's where i would start.
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.documentclass.saved(office.11).aspx
Sorry about the links i've had to remove the protocol heading because stack doesn't think i should be able to have more than one link in my answers because i'm not a real member
I solved 2 minutes ago the same problem.
When you add/change custom properties seems that the document is no changed, so the WordApplication.ActiveDocument.Saved is still true.
Set it to false and then call the Save method of the Document, it will work!!