Merge RTF Files

I have an RTF set stored in strings in C #, this is their way to combine them into one document for printing, because the user wants to print them as one document with print settings appearing once. I can use service communication if necessary, obviously avoiding it better.

Edit: a page break is needed for each document, I think I can just insert a \ page for this, though

+6
c # rtf
source share
7 answers

Here you go (C # code included)

0
source share

You will need to remove the trailing} from the first document.

You will need to remove the sections {\ rtf1 ... and {fonttbl .. and {colortbl ......] from the second document. You may need to look at any heading, fields, etc. that you may have.

Divide them into the \ page as you say.

This assumes that the fonts and color tables are the same.

It might be better to get print settings from the user, then quietly print each document separately, if this is an option.

Document 1:

{\rtf1\ansi\ansicpg1252\deff0\deflang5129 {\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}} {\colortbl;\red0\green0\blue0;} \margl1134\margr1134\margt1134\margb1134\sectd \pard Document One Content \line } 

Document 2:

 {\rtf1\ansi\ansicpg1252\deff0\deflang5129 {\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}} {\colortbl;\red0\green0\blue0;} \margl1134\margr1134\margt1134\margb1134\sectd \pard Document Two Content \line } 

Consolidated documents:

 {\rtf1\ansi\ansicpg1252\deff0\deflang5129 {\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}} {\colortbl;\red0\green0\blue0;} \margl1134\margr1134\margt1134\margb1134\sectd \pard Document One Content \page \pard Document Two Content \line } 
+4
source share

Just deleting the font table will only work if both documents use the same font set. You will need to uniquely merge the font tables (font element wise) if you want to save font information like for rtfs. This will work for the n number of rtfs, but again, we need to join separate font tables. I am currently working on developing code for this union, which will be published once ...)

In our project, we also used the Office Doc object to render rtfs and use word automation. But it creates a dependency on the installed ms-word. In particular, this can cause problems if the code is to be run from a server, where memory is also a concern, because using the API word will load an instance of the ms word into memory. But the solution really works!

Good!! So, it's ready with the code to join the Font tables in two rtfs and merge them to save different fonts. Please read RTF in lines.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; //Arjun 02nd May namespace MergeRtf { class RTFUtils { public static string getRTFBlock(string blockName,string rtf){ int i=rtf.IndexOf(@"{\"+blockName); int startOfBlock = i; //Next find the end of style sheet element tag Stack<char> braceHolder=new Stack<char>(); braceHolder.Push('{'); string stylesheetBlock = ""; while (braceHolder.Count != 0&&i<rtf.Length) { i++; if (rtf[i] == '{') { braceHolder.Push('{'); continue; } if (rtf[i] == '}') { braceHolder.Pop(); } } if (braceHolder.Count == 0) { //encountered the ending tag for stylesheet stylesheetBlock = rtf.Substring(startOfBlock, i-startOfBlock+1); return stylesheetBlock; } else { //Error in doc format throw (new Exception("Error in doc format")); } } public static string MergeRTFs(string rtf1,string rtf2,string mergingBreak){ //mergingBreak is the type of break that will be sandwiched between the docs //get the fonttbl blocks for both the documents string fontTableOfDoc1 = getRTFBlock("fonttbl", rtf1); string fontTableOfDoc2 = getRTFBlock("fonttbl", rtf2); //get font lists List<string> fontList1 = ExtractRTFFonts(fontTableOfDoc1); List<string> fontList2 = ExtractRTFFonts(fontTableOfDoc2); //Union the font list IEnumerable<string> mergedfonts = fontList1.Union(fontList2); List<string> fontList3 = new List<string>(mergedfonts); string mergedFontListBlock = @"{\fonttbl"; foreach (string font in fontList3) { mergedFontListBlock += font; } mergedFontListBlock += "}"; //Find location of the fonttable in doc 1 and doc 2 int indexOfFontTable1 = rtf1.IndexOf(@"{\fonttbl"); int indexOfFontTable2 = rtf2.IndexOf(@"{\fonttbl"); string rtfMerged = ""; //Get rtf content before and after fonttable string headerRTF1 = rtf1.Substring(0, indexOfFontTable1); int endOfFontTableIndex=indexOfFontTable1 + (fontTableOfDoc1.Length-1); string trailerRTF1 = rtf1.Substring(endOfFontTableIndex + 1, rtf1.LastIndexOf('}') - (endOfFontTableIndex + 1)); //-2 to remove ending } of 1st doc //create the first rtf with merged fontlist rtfMerged = headerRTF1 + mergedFontListBlock + trailerRTF1; //next identify trailer part after font table in rtf 2 string trailerRTF2 = rtf2.Substring(indexOfFontTable2 + fontTableOfDoc2.Length); rtfMerged += mergingBreak + trailerRTF2; return rtfMerged; } private static List<string> ExtractRTFFonts(string fontTableBlock) { Stack<char> braces = new Stack<char>(); List<string> fonts = new List<string>(); int fontDefStart=0,fontDefLength; braces.Push('{'); int i=0; while (braces.Count > 0 && i < fontTableBlock.Length) { i++; if (fontTableBlock[i] == '{') { braces.Push('{'); if (braces.Count == 2) { //means font definition brace started store the position fontDefStart = i; } continue; } if (fontTableBlock[i] == '}') { braces.Pop(); if (braces.Count == 1) { //means only root level brace left identifying one font definition ended fontDefLength = i - fontDefStart + 1; fonts.Add(fontTableBlock.Substring(fontDefStart,fontDefLength)); } } } if (braces.Count == 0) { //everything is fine then return fonts; } else { //malformed font table passed throw (new Exception("Malformed font table passed")); } } } } 
+3
source share

You can use two rich text fields. Read the rtf file into one text box (rtbTemp), and then cut and paste the text into another (rtbMerged). For example:

 RichTextBox rtbTemp = new RichTextBox(); RichTextBox rtbMerged = new RichTextBox(); string Merge(string s1, string s2) { rtbTemp.Rtf = s1; rtbTemp.SelectAll(); rtbTemp.Cut(); rtbMerged.Paste(); rtbMerged.AppendText(Environment.NewLine); rtbMerged.AppendText(Environment.NewLine); rtbTemp.Rtf = s2; rtbTemp.SelectAll(); rtbTemp.Cut(); rtbMerged.Paste(); return rtbMerged.Rtf; } 
+2
source share

I guess there is a way to do this without going into the details of the RTF format. Save RTF as files and use Automation MS Word to open and add documents to each other (then save again as RTF).

0
source share

I used this code two merges with rtf files , use the merge method from the file path. If you only have text, you can change it, but if you have a larger document, you will have a memory error. Sorry for my english.

0
source share

I remove only 3 charecter from the end of the first rtf file and one of the first char of the second rtf file, and it works well!

 RichTextBox r = new RichTextBox(); r.Rtf = rtf1.Rtf.Substring(0, rtf1.Rtf.Length - 3) + rtf2.Rtf.Substring(1,rtf2.Rtf.Length - 1) 
0
source share

All Articles