Merge RTF files

守給你的承諾、 提交于 2019-12-01 17:27:17

Here you go (C# code's included in)

You would have to remove the trailing } from the first document.

You would have to remove the {\rtf1... and {fonttbl.. and {colortbl... sections from the second document. Might need to look at any header, margins etc. that you might have.

Separate them by a \page as you say.

This assumes the font and color tables are the same.

Probably better to get the print settings from the user then silently print each document separately, if that's 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
}

Merged 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
}
  • This doesn't work for more complex RTF's like the ones I have. I ended up using interop for now. – PeteT Mar 21 '09 at 0:14
  • This will also not work for documents that don't share the font and color tables exactly – Beta033 Nov 10 '11 at 23:34
3

Just removing the font table will work only if both documents use the same set of fonts. You will need to uniquely merge (union) the font tables (font element wise) if you want to preserve font info of both the rtfs. This will work for n number of rtfs but again we need the union of individual font tables.. I am currently workin on developing the code for this union will post once ready.. :)

In our project we also used the Office Doc object to render rtfs and benefit from word's automation. But it creates a dependency of having ms-word installed. Particularly it can raise problem if the code needs to run from a server where memory is also a concern as using word API causes instance of ms-word to be loaded in memory. But the solution does work!!

Okay!! So ready with the code for union of Font tables in two rtfs and merging them to preserve varying fonts..Please read the RTFs in strings.

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"));
        }
    }


}
} 
  • i don't think this will work. this is not updating the codes in the second document as they are applied. what i mean is, in the second document /f2 may be applied to some text, but /f2 is now /f14 in the merged table, so all /f2 codes in the second document have to be updated to /f14 for the font to be maintained. – Beta033 Nov 10 '11 at 23:01
2

You can use two rich text boxes. Read the rtf file into one rich text box (rtbTemp), and then cut and paste the text into the other (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;
}
  • Unfortunately doesn't work with images in the RTF file :( – Florian Straub Sep 2 at 7:33
0

I guess there's also a way of doing this without getting into the details of the RTF format. Save your RTFs as files and use Automation of MS Word to open and append documents to each other (then save again as RTF).

  • Think this is the approach I will end up taking, just wondering if i can do it without writing the temporary separate files now. – PeteT Mar 10 '09 at 1:41
0

I've used this code two merge to rtf files, use de method Merge wiht de path of de files. If you have only de text you can modify it, but if you have bigger document you will be in a error of memory. I'm sorry for my english.

  • code to merge two rtf files – Anonymous Apr 17 '09 at 12:42
0

I only remove 3 charecter from end of first rtf file, and one of first char of second rtf file and it work good!

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

    Your Answer

    By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

    Not the answer you're looking for? Browse other questions tagged or ask your own question.

    标签
    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!