I am trying to export a FlowDocument which contains a grid to rtf. I used the following code
using (FileStream fs = new FileStream(#"C:\demo.rtf", FileMode.OpenOrCreate, FileAccess.Write))
{
TextRange textRange = new TextRange(doc.ContentStart, doc.ContentEnd);
textRange.Save(fs, DataFormats.Rtf);
}
However I am getting a blank document. How can this be solved?
I had a similar issue recently and the culprit turned out to be the
FileMode.OpenOrCreate
It should have been
FileMode.Create
instead.
When you use OpenOrCreate and the file already exists and has more content than you are writing into it you will end up with the end of the old file after the end of the new content. Word or WordPad or whatever you are trying to open it in may not be able to interpret it correctly but makes an attempt to show you what it can which may be in your case a blank page.
The second issue that may be part of the problem is the viewer you use to open it and the FlowDocument you use to write it may not be on the same wave length to put it mildly.
You may notice that WordPad for example displays the same rtf file differently than Word.
They also produce very different files when you save them.
Same goes for the FlowDocument - it may be saving something that for example WordPad or even Word (though this is less likely) is not able to display correctly (or at all).
Related
TL;DR:
How can I capture the paragraph numbering as a 'part' of the text and export it to a DOCX?
Problem
I have a document that's split into sections and sub-sections that reads similarly to a set of state statutes (Statute 208, with subsections Statute 208.1, Statute 208.2, etc.). We created this by modifying the numbering.xml file within the .docx zip.
I want to export a 'sub-section' (208.5) and its text to a separate .docx file. My VSTO add-in exports the text well enough, but the numbering resets to 208.1. This does make some sense as it's now the first paragraph with that <ilvl> in the document.
PDF works okay
Funnily enough, I'm able to call Word.Range's ExportAsFixedFormat function and export this selection to PDF just fine - even retaining the numbering. This led me down a path of trying to 'render' the selection, possibly as it would be printed, in order to throw it into a new .docx file, but I haven't figured that out, either.
What I've tried:
Range.ExportFragment() using both wdFormatStrictOpenXMLDocument and wdFormatDocumentDefaultas the wdSaveType values.
These export but also reset the numbering.
Document.PrintOut() using PrintToFile = true and a valid filename. I realize now that this, quite literally, generates 'printout instructions' and won't inject a new file at path filename with any valid file structure.
Plainly doesn't work. :)
Application.Selection.XML to a variable content and calling Document.Content.InsertXML(content) on a newly added Document object.
Still resets the numbering.
Code Section for Context
using Word = Microsoft.Office.Interop.Word;
Word.Range range = Application.ActiveDocument.Range(startPosition, endPosition);
range.Select();
//export to DOCX?
Application.Selection.Range.ExportFragment(
filename, Word.WdSaveFormat.wdFormatDocumentDefault);
You could use ConvertNumbersToText(wdNumberAllNumbers) before exporting, then _Document.Undo() or close without saving after the export.
There is some good information at this (dated) link that still should work with current Word APIs:
https://forums.windowssecrets.com/showthread.php/27711-Determining-which-ListTemplates-item-is-in-use-(VBA-Word-2000)
Information at that link suggests that you can create a name/handle for your ListTemplate so that you can reference it in code--as long as your statute-style bullets are associated with a named style for the document. The idea is to first name the ListTemplate that's associated with the statute bullet style for the active document and then reference that name when accessing the ListLevels collection.
For instance, you could have code that looks something like this:
ActiveDocument.Styles("StatutesBulletStyle").ListTemplate.Name = "StatuteBulletListTemplate";
After the above assignment, you can refer to the template by name:
ActiveDocument.ListTemplates("StatuteBulletListTemplate").ListLevels(1).StartAt = 5;
Using the above technique no longer requires that you try to figure out what the active template is...
Does that help?
I am looking at the feasibility of creating something using C# and iTextSharp that can take a PDF template and replace various place holder values with actual values retrieved from a database. Essentially a PDF mail merge. I have the iText in action book but it covers rather a lot of stuff i don't need and I am struggling to find anything related to what i want to do. I am happy to use PDF fields as the place holders so long as the merged/flattened form does not look like it has fields in it, the output document should look like a mail merged letter and not a form that has been filled in. In an ideal world i just want search the text content of the PDF and then replace text place holders with their correct field values a la word mail merge.
Can anyone advise me of the best approach to this and point me in the direction of the most helpful iTextSharp classes to use, or if you know the iText in Action book a pointer to the most helpful section for me to read.
Build your template sans fields in your page-layout/text-editor of choice.
Save to PDF.
Open that PDF and add fields to it. This is easy to do in Acrobat Pro (you could download a trial if need be). It's also possible in iText, just much harder.
In either case, you want to set your form fields to have no border, and no background... that way only their contents will be visible, no boxes to make your fields look like fields.
Merging field data into a form is Quite Trivial with iText (forgive my Java, I don't know much about C#):
void fillPDF( String filePath, Map<String, String> fieldVals ) {
PdfReader reader = new PdfReader(myFilePath);
PdfStamper stamper = new PdfStamper( reader, outputFileStream );
stamper.setFormFlattening(true);
AcroFields fields = stamper.getAcroFields();
for (String fldName : fieldVals.keySet()) {
fields.setField( fldName, fieldVals.get(fldName) );
}
stamper.close();
}
This ignores list boxes with multiple selections (and exceptions), but other than that should be ready to go. Given that you're doing a mail-merge type thing, I don't think multiple selections will be much of an issue.
I have a windows application to generate report.
It has templates in RTF as "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang2057{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}\r\n\\viewkind4\\uc1\\pard\\fs20\\tab\\tab\\tab\\tab af\\par\r\n}\r\n", which is written to word doc file. then the word is Saved-As XML and close. Then, tags like (say) are extracted and some new
The problem here is Word, which is used as converter in the process and it consumes valuable time in Loop, where it opens word instance, save, close, delete.
Please correct any mistake if i have made and help me with an alternative to convert to WordML .
Use Aspose .Words
//your rtf string
string rtfStrx = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang2057{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}\r\n\\viewkind4\\uc1\\pard\\fs20\\tab\\tab\\tab\\tab af\\par\r\n}\r\n"
//convert string to bytes for memory stream
byte[] rtfBytex = Encoding.UTF8.GetBytes(rtfStrx);
MemoryStream rtfStreamx = new MemoryStream(rtfBytex);
Document rtfDocx = new Document(rtfStreamx);
rtfDocx.Save(#"C:\Temp.xml", SaveFormat.WordML);
This saves your RTF text in new document as WordML. I cannot say about time it will take in loop. But it will surely have much less time then MS Word being physically opened and closed.
Unless I am missing something, I assume that you are trying to create Office XML file from RTF template? I think you can use Open XML SDK for creation of the xml file. Specifically, DocumentReflector that comes with that SDK seems to a good fit for that. See this example. Also, there is a http://www.codeguru.com/cpp/controls/richedit/conversions/article.php/c5377/ which shows how to convert from RTF to HTML that might guide you.
use wpf richtextbox. Rtf => xaml. Since xaml is xml_ use xslt or linq to convert it to your desired xml structure
How to make text bold using stream writer,here is my code:
string path = Application.StartupPath + "\\WZ.PNR";
StreamWriter writer = new StreamWriter(path);
textPrint.ToText(writer, Width, FSection, FAlign, DSection, DAlign, Format);
writer.WriteLine();
writer.Close();
I am writing some text and i need to make some text BOLD, How to do it?
Thanks
StreamWriter is for writing plain text. You need markup of some kind to make text bold. Options include:
RTF
HTML
TeX
How are you expecting to open the generated file? The application will need to understand whatever file format you choose. There's no general concept of "a bold character" - the letter E is the letter E; if you want it styled that styling data is separate.
Given your file extension, are you trying to create a PeerNet Label Designer file? If so, you'll need to find out the appropriate file format - I don't know whether it's a text format, binary etc.
At first you should create your path in that way:
string path = Path.Combine(Application.StartupPath, "WZ.PNR");
After this little improvement let's take a look at your pnr file...
So you open this file and like to write some bold text to it?
So do you have some kind of program, that is already able to create and view such a .pnr file?
I think you'll have, or from where do you know, that it is possible to have bold text within such a file?
In case you have this program to generate such a file with bold text. Just make a new file, enter three words: "one two three" and make the 'two' bold. Save this file and open it with a good plain text editor (e.g. notepad++) or a good Hex-Editor and try to find out how this will be accomplished.
For example, open WordPad create a new rtf-File and insert the above example. After saving it and re-opening in a plain text editor you'll get:
{\rtf1\ansi\ansicpg1252\deff0\deflang1031{\fonttbl{\f0\fswiss\fcharset0 Arial;}}
\viewkind4\uc1\pard\f0\fs20 one \b two\b0 three\par
}
And as you can see, the bold is been made by using '\b ' to enable and '\b0 ' to disable the bold text. Also there is plenty of other informations like used font, charset, etc.
That's called reverse-engineering if you don't have any specs. ;-)
The extension PNR suggests some sort of Printer file. That means you'll have to look up the escape codes for that particular kind of printer.
I have loaded a memorystream with a word document and I want to be able to alter specific text within the memorystream and save it back to the word document, like search and replace functionality. Please can anyone help me with this as I don't want to use the Word Interop libraries. I have the code to load and save the document already, please see below. The problem is, if I convert the memorystring to a string and use the string replace method, when I save the string all the formatting within the word document is lost and when I open the document all it shows is black boxes all over the place.
private void ReplaceInFile(string filePath, string searchText, string replaceText)
{
byte[] inputFile = File.ReadAllBytes(filePath);
MemoryStream memory = new MemoryStream(inputFile);
byte[] data = memory.ToArray();
string pathStr = Request.PhysicalApplicationPath + "\\Docs\\OutputDocument.doc";
FileInfo wordFile = new FileInfo(pathStr);
FileStream fileStream = wordFile.Open(FileMode.Create, FileAccess.Write, FileShare.None);
fileStream.Write(data, 0, data.Length);
fileStream.Close();
memory.Close();
}
I copied the code from sample code on the internet. So That is why memorystream was used as I had no idea how to do it. My issue is the company I work for doesn't want to use the word interop as sometimes they have found that word can display popup dialog boxes on occassion that prevents the coded functionality from executing. This is why I want to look at ways of achieving a mail merge functionality but in a programmatical way. I did do a very similar thing to what I want to do here many years ago but in Delphi not C# and I have typically lost the code. So if anyone can shed any light on this then I would be grateful.
You will have to use the Word interop libraries - or at least something similar. It's not like Word documents are just plain text documents - they're binary files. Converting the bytes into a string and doing a replace that way is going to break the document completely.
With the new open formats you may be able to write your own code to parse them, but it's going to be significantly harder than using a library.
Your best bet is to convert the file to OOXML - then that's an XML file which you can update programmatically using a string find / replace, System.XML or LINQ.
(See http://blogs.msdn.com/b/ericwhite/archive/2008/09/19/bulk-convert-doc-to-docx.aspx for more info on the server side conversion process.)