I'm attempting to create a word document, but text between certain words should be crossed out. I tried looking online for solutions but the only solution I could find was:
Set myRange = document.Range(Start:= document.Words(1).Start, _End:= document.Words(3).End)
myRange.Font.StrikeThrough = True
from here https://msdn.microsoft.com/en-us/vba/word-vba/articles/font-strikethrough-property-word for VBA. Unfortunately there was nothing for C#.
Does anyone know how you would add a strike-through to specific pieces of text before saving it all to a word document?
My code for reference:
//input is a StringBuilder received by method
try {
//Create an instance for word app
Microsoft.Office.Interop.Word.Application winword = new Microsoft.Office.Interop.Word.Application();
//Set animation status for word application
winword.ShowAnimation = false;
//Set status for word application is to be visible or not.
winword.Visible = false;
//Create a missing variable for missing value
object missing = System.Reflection.Missing.Value;
//Create a new document
Microsoft.Office.Interop.Word.Document document = winword.Documents.Add(ref missing, ref missing, ref missing, ref missing);
//adding text to document
document.Content.SetRange(0, 0);
document.Content.Text = input.ToString();
//Save the document
object filename = #"C:\Users\TempUser\Desktop\temp1.docx";
document.SaveAs2(ref filename);
document.Close(ref missing, ref missing, ref missing);
document = null;
winword.Quit(ref missing, ref missing, ref missing);
winword = null;
Console.WriteLine("Document created successfully!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
I've extracted the relevant part from your code to make it easier to follow.
My assumption with this sample is that text should be inserted at the end of the document and formatted as "strikethrough". Notice how I declare a Word.Range object and assign the body of the document to it. For understanding how it works, think of a Range like a Selection, but you can have more than one and it's not visible in the document.
The next line "collapses" the Range to its end-point - like pressing Right arrow. If you did not collapse the Range, the text assigned to it would replace what's in the document (like over-typing a selection). The text is then assigned to the Range and the Strikethrough applied.
Note that in the old Word Basic days "true" and "false" were not concepts used for setting font decoration. Word's object model still uses these old Word Basic commands. Under the covers they still use -1 for true and 0 for false (and sometimes 1 for something else). While the VB languages can use the "pseudo boolean" settings (true/false) that have been added to the object model for convenience, C# doesn't "see" them, so you need -1 for true.
//adding text to document
object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
Word.Range rng = document.Content;
rng.Collapse(ref oCollapseEnd);
rng.Text = input.ToString();
rng.Font.Strikethrough = -1; // 0 for false
Related
I want to create application to fill template documents automated by C# Interop.Word library. User chooses template document from existing files. I have to clone this document to the new document (including padding, margin and all the format).
1.I have tried to use InsertFile function
document = app.Documents.Add();
object missing = System.Reflection.Missing.Value;
object start = 0;
object end = 0;
Word.Range range = document.Range(ref start, ref end);
range.InsertFile(template_file_name, ref missing, ref _true, ref missing, ref missing);
and filling template inside document. But this function changes some of the formats from template
2. I have tried using Copy and PasteSpecial
app=new Word.Application();
src_doc=app.Documents.Open(template_file_name);
document=app.Documents.Add();
src_doc.Content.Copy();
document.Content.PasteSpecial(DataType:Word.WdPasteOptions.wdKeepSourceFormatting);
This code keeps format correct. But after pasting it is problematic to change value. "src_doc" keeps open even after closing it.
Long story short. Need to clone existing document as a new Document
This can be achieved by passing a file path to the Docments.Add method:
Word.Application _word = new Word.Application();
_word.Visible = true;
_word.WindowState = Word.WdWindowState.wdWindowStateMaximize;
Word.Document _doc = _word.Documents.Add(pathToExistingDocument);
I can add a signature line to the word document but i feel not good with my approach. I've searched a lot to handle my sitautation but not found any.
Well here is my code
private void CreateNewPage()
{
object missing = System.Reflection.Missing.Value;
object fileName = #"C:\docs\mydoc.docx";
object readOnly = false;
object isVisible = true;
//Start Word and open a document.
Word._Application oWord;
Word._Document oDoc;
oWord = new Word.Application();
oWord.Visible = true;
oDoc = oWord.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref isVisible, ref missing,
ref missing, ref missing, ref missing);
// var numberOfPages = oDoc.ComputeStatistics(Word.WdStatistic.wdStatisticPages, false);
object oEndOfDoc = "\\endofdoc";
object paramNextPage = Word.WdBreakType.wdSectionBreakNextPage;
oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range.InsertBreak(ref paramNextPage);
//Insert a page break
object breakPage = Word.WdBreakType.wdPageBreak;
object saveOption = Word.WdSaveOptions.wdDoNotSaveChanges;
object originalFormat = Word.WdOriginalFormat.wdOriginalDocumentFormat;
object routeDocument = false;
object what = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToPage;
object which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToLast;
object count = 3;
oWord.Selection.GoTo(ref what, ref which, ref count, ref missing);
object sigID = "{00000000-0000-0000-0000-000000000000}";
Timer t = new Timer();
t.Elapsed += (sender, args) =>
{
SendKeys.SendWait("{TAB}");
SendKeys.SendWait("~");
t.Stop();
};
t.Interval = 2000;
t.Start();
try
{
oWord.Activate();
SignatureSet signatureSet = oWord.ActiveDocument.Signatures;
// signatureSet.ShowSignaturesPane = false;
Signature objSignature = signatureSet.AddSignatureLine(sigID);
objSignature.Setup.SuggestedSigner = "docSigner";
objSignature.Setup.SuggestedSignerEmail = "abc#xyz.com";
objSignature.Setup.ShowSignDate = true;
// dynamic shape = objSignature.SignatureLineShape;
}
catch (Exception ex){}
oWord.Documents.Save();
oWord.Quit();
try
{
Marshal.ReleaseComObject(oWord);
}
catch (Exception){}
}
Well as you see below, when i call AddSignatureLine funciton, this window opens modal (like showdialog) and until close this, the code does not flow..
and I am bypass this by using sendkey but we know that it is not a good way. However, If i cant find any other solution then I will try to do that finding this window (word's child window) using Win32 APIs.
But I am curious if is there anyway to bypass this? Because there are thousand documents and I am looking for also a faster way.
After adding this signature line, then we can able to sign document with DocuSign. But if there is no any signature line in the document, DocuSign does not sign the document digitally. Then We have to add this line.
As there seems no way of circumventing the display of the modal Signature Setup dialog, I would suggest you the following workaround which is based on a building block containing a properly configured signature line:
Create a new empty .dotx template. This template will be used to save the building block entry.
Create a sample document containing a signature line and add this signature line via Insert > Quick Parts > Save Selection to Quick Part Gallery to the template created in the previous step.
Include the template in your project and deploy the template with your executable or add-in.
At runtime, load the template as an add-in
Application.AddIns.Add(fullPathToDotx);
You can now insert the building block from the template
var template = Application.Templates
.OfType<Microsoft.Office.Interop.Word.Template>()
.FirstOrDefault(t => t.Name == addInFileName);
var buildingBlock = template.BuildingBlockEntries.Item("Signature Line");
buildingBlock.Insert(range, true);
(Unload the building block template)
If you need to modify the properties of the signature line, you could either
Prepare multiple signature line building blocks which are configured accordingly, or
Dynamically patch the building block template (e.g. by creating a copy at runtime, open and manipulating the file using the Open XML SDK and temporarily load the modified version.
Using the following code to open a Word document at a bookmark
Object readOnly = true;
Object isVisible = true;
Object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document wordDoc = new Microsoft.Office.Interop.Word.Document();
wordApp.Visible = true;
wordDoc = wordApp.Documents.Open(ref fileName, ref missing, ref readOnly, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible,
ref missing, ref missing, ref missing, ref missing);
object bookmarkName = BookMarkName;
if (wordDoc.Bookmarks.Exists(bookmarkName.ToString()))
{
Microsoft.Office.Interop.Word.Bookmark bookmark = wordDoc.Bookmarks.get_Item(ref bookmarkName);
bookmark.Select();
}
The Word document shows the bookmark, but not at the top of the page. Is there a way of showing the Bookmark at the top of the page as it is shown using Goto-> Bookmark?
The code suggested in StackOverflow Question
How do I use the Microsoft Word API and Bookmarks feature to programmatically open a Word document to a specific location?
which is
Object item = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToBookmark;
Object whichitem = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToFirst;
Object count = 1;
Object name = BookMarkName;
wordDoc.GoTo(ref item, ref missing, ref missing, ref name);
does not work and gives all the errors described in the post.
GotoBookmark in MS Word
In pascal work this code:
procedure GotoBookMark(name:string);
var d1,d2,d7,d8:olevariant;
begin
d1:=name;
d2:= wdGoToBookmark;
d7:=unAssigned;
d8:=unAssigned;
try
WA.selection.GoTo_(d2, d7,d8,d1);
except
end;
end;
Where name name of bookmark;
wa is Microsoft.Office.Interop.Word.Application wa= new Microsoft.Office.Interop.Word.Application();
open document MS Word
procedure OpenWordDoc(Name:string);
var FileName,Visible,newtemplate,documenttype:olevariant;
begin
FileName:=Name;
newtemplate:=false;
documenttype:=0;
visible:=true;
WA.Documents.Add( FileName,newtemplate,documenttype,visible);
end;
This is tricky, since Word VBA isn't really screen-oriented. The following code does work on my screen, but you'd need to test to be sure it works in other configurations. You might need to adjust the "fudge factor" (the literal 40). In any case, though, it should get the bookmark near the top of the screen, within a line or so.
The Window.GetPoint method returns the position in pixels of the Range - it's a Windows API method that's been brought into VBA, which is why you have to pass in the variables, which are then populated with the values.
The Window height less the usable height, plus the "fudge factor" gives you the position in points of the visible top of the document. The Window is scrolled line-by-line until the position returned by GetPoint is no longer greater than this position.
Sub ScrollBookmarkTopOfPage()
Dim rng As word.Range
Dim pxLeft As Long, pxTop As Long, pxWidth As Long, pxHeight As Long
Dim winUseHeight As Long, winHeight As Long, pos As Long
Set rng = ActiveDocument.Bookmarks("test").Range
ActiveWindow.GetPoint pxLeft, pxTop, pxWidth, pxHeight, rng
'Debug.Print pxLeft, pxTop, pxWidth, pxHeight
winUseHeight = ActiveWindow.UsableHeight
winHeight = ActiveWindow.height
pos = winHeight - winUseHeight + 40
Do While PixelsToPoints(pxTop) > pos
ActiveWindow.SmallScroll
ActiveWindow.GetPoint pxLeft, pxTop, pxWidth, pxHeight, rng
Loop
rng.Select
End Sub
I am using:
Office 2007
VC# Express 2010
1x Citrix virtual XP network environment accessed through Windows 7 laptop host
1x printer set to output to .prn in a given network-mapped drive
I am using C# and Word Interop to silently print a given set of files automatically. The application scans an input folder every 10 minutes for .doc / .docx files only, and inputs their path&filename into a list. Foreach found file, attempt to print via the following code:
public static Boolean PrintFoundFiles(List<string> foundFiles)
{
successful = false;
foreach (string file in foundFiles)
{
object fileAndPath = file; //declare my objects here, since methods want an object passed
object boolTrue = true; //
object boolFalse = false; //
object output = FormatOutputName(file); //
object missing = System.Type.Missing; //
object copies = "1"; //
object pages = ""; //
object items = Word.WdPrintOutItem.wdPrintDocumentContent; //
object range = Word.WdPrintOutRange.wdPrintAllDocument; //
object pageType = Word.WdPrintOutPages.wdPrintAllPages; //
Word.Application wordApp = new Word.Application(); //open word application
wordApp.Visible = false; //invisible
Word.Document doc = wordApp.Documents.Open(ref fileAndPath, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing); //opens the word document into application behind the scenes
doc.Activate(); //activates document, else when I print the system will throw an exception
wordApp.ActivePrinter = "my printer name"; //Specify printer I will print from
doc.PrintOut(ref boolTrue, ref boolFalse, ref range, ref output, ref missing, ref missing,
ref items, ref copies, ref pages, ref pageType, ref boolTrue, ref boolTrue,
ref missing, ref boolFalse, ref missing, ref missing, ref missing, ref missing);
doc.Close(SaveChanges: false);
doc = null;
((Word._Application)wordApp).Quit(SaveChanges: false); //kill word process the right way
wordApp = null; //reset to null
successful = true;
}
return successful;
}
After I receive the true boolean of "successful", I will back up the file automatically in a backup folder, delete it in the input folder, and look for the .prn in the output folder (it just sits here for processing later).
If I don't provide an output (see ref output on doc.PrintOut()), the output directory doesn't get updated or printed to at all. If I DO provide an output, the .prn is created, though it is a 0kb empty file.
The printer is set up as the default printer, and it has been configured to automatically output to said output folder. If I open Word manually with the same file I'm trying to automatically print from, hit print, it will create a 6kb .prn file in the output directory without having to hit anything other than CTRL + P, OK.
I'm fairly confident the file is being opened OK via "Word.Document doc = wordApp.Documents.Open()" because I did a doc.FullName and got the full path of the input word document in question. I just cannot for the life of me get the .prn to output correctly to the output folder.
If I start my word (2010) and record a macro of me pressing Ctrl+P and hitting print - I'm getting
Application.PrintOut fileName:="", Range:=wdPrintAllDocument, Item:= _
wdPrintDocumentWithMarkup, Copies:=1, Pages:="", PageType:= _
wdPrintAllPages, Collate:=True, Background:=True, PrintToFile:=False, _
PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
Change your PrintOut to reflect what Word did and see if it solves your issue.
There's no reason to be "fairly confident", just remove
wordApp.Visible = false
Debug your program and make certain it's OK.
I have got about 200 word documents that I need to pdf.
Obviously, I cannot pdf them one by one as, first it will take ages, second I am sure it is not good practice to do so.
I need to find a way to automate that conversion, since we will need to this again and again.
I use C#, but the solution does not necessarily have to be in c#, but it is preferred.
I have had a look at few libraries such as PDfCreator, Office 2007 add-in, ITextSharp, and so forth and there is not any clear answer on the forums.
PDFCreator has c# sample, but it does only work with txt files.
Office 2007 add in does not have document locking capabilities which a must on the automation.
has anyone implemented such scenario before? I would like you hear your suggestions.
Thanks in advance
regards
You can try the method in this blog post:
http://angrez.blogspot.com/2007/06/create-pdf-in-net-using-pdfcreator.html
I'm doing this to automate the conversion of our doc and docx documents to pdf:
private bool ConvertDocument(string file)
{
object missing = System.Reflection.Missing.Value;
OW.Application word = null;
OW.Document doc = null;
try
{
word = new OW.Application();
word.Visible = false;
word.ScreenUpdating = false;
Object filename = (Object)file;
doc = word.Documents.Open(ref filename, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing);
doc.Activate();
if (Path.GetExtension(file) == ".docx")
file = file.Replace(".docx", ".pdf");
else
file = file.Replace(".doc", ".pdf");
object fileFormat = OW.WdSaveFormat.wdFormatPDF;
doc.ExportAsFixedFormat(file, OW.WdExportFormat.wdExportFormatPDF, false, OW.WdExportOptimizeFor.wdExportOptimizeForPrint,
OW.WdExportRange.wdExportAllDocument, 1, 1, OW.WdExportItem.wdExportDocumentContent, true, true, OW.WdExportCreateBookmarks.wdExportCreateNoBookmarks,
true, true, false, ref missing);
}
catch(Exception ex)
{
return false;
}
finally
{
if (doc != null)
{
object saveChanges = OW.WdSaveOptions.wdDoNotSaveChanges;
((OW._Document)doc).Close(ref saveChanges, ref missing, ref missing);
doc = null;
}
if (word != null)
{
((OW._Application)word).Quit(ref missing, ref missing, ref missing);
word = null;
}
}
return true;
}
where OW is an alias for Microsoft.Office.Interop.Word.
Have you check this MSDN article?
Edit:
Notice that this "How To" samples will not work as-is because:
For some reasons it runs over the program parameters (ConvertDocCS.exe [sourceDoc] [targetDoc] [targetFormat]) in line #77, #81 & #82.
I converted the project to VS 2010 and had to re-reference Microsoft.Office.Core. It's a COM reference called Microsoft Office 12.0 Object Library.
The sample do not except a relative path.
I'm sure you will manage to overcome those obstacles :)
One last thing. If you are working with .NET 4 you don't need to send all those annoying Missing.Value thanks to the wonder of optional parameters.
You may try Aspose.Words for .NET to convert DOC files to PDF. It can be used in any .NET application with C# or VB.NET like any other .NET assembly. It also work on any Windows OS and in 32/64-bit systems.
Disclosure: I work as developer evangelist at Aspose.
As HuBeZa said, if Word is installed on your workstation, you can use Word Automation to open your files one by one and save them as PDF.
All you need is referencing the COM component "Microsoft Word Object Library" and play with the classes of this assembly.
The execution time will probably a bit long, but your conversions will be automated.
We can set fonts for word automation, I applied single font to all generated documents from my solution for same application- and saved my time to manually go in each template and set the font separately for each tag and heading and etc...
using (WordprocessingDocument wordProcessingDocument = WordprocessingDocument.Open(input, true))
{
// Get all content control elements
List<DocumentFormat.OpenXml.OpenXmlElement> elements =
wordProcessingDocument.MainDocumentPart.Document.Body.ToList();
// Get and set the style properties of each content control
foreach (var itm in elements)
{
try
{
List<RunProperties> list_runProperties =
itm.Descendants<RunProperties>().ToList();
foreach (var item in list_runProperties)
{
if (item.RunFonts == null)
item.RunFonts = new RunFonts();
item.RunFonts.Ascii = "Courier New";
item.RunFonts.ComplexScript = "Courier New";
item.RunFonts.HighAnsi = "Courier New";
item.RunFonts.Hint = FontTypeHintValues.ComplexScript;
}
}
catch (Exception)
{
//continue for other tags in document
//throw;
}
}
wordProcessingDocument.MainDocumentPart.Document.Save();
}
I think straight answer to this is no!!!
but it is possible through workaround what i suggest is use imagemagik or some library and see if it can provide images of your word doc and then use these images in itextsharp to create pdf