Объединить RTF-файлы
У меня есть набор RTF, хранящихся в строках в C#, это их способ объединить их в один документ для печати, поскольку пользователь хочет напечатать их как один документ с настройками печати, появляющимися один раз. Я могу использовать office interop при необходимости, очевидно, избегая этого лучше.
Edit: разрыв страницы будет необходим между каждым документом, я думаю, что могу просто вставить page для этого, хотя
7 ответов
вам придется удалить трейлинг } из первого документа.
вам придется удалить {\rtf1... и {fonttbl.. и {colortbl... разделы из второго документа. Возможно, потребуется посмотреть на любой заголовок, поля и т. д. возможно, так оно и было.
разделите их на \page, как вы говорите.
предполагается, что таблицы шрифтов и цветов одинаковы.
вероятно, лучше получить настройки печати от пользователя, а затем молча распечатать каждый документ отдельно, если это возможно.
документ 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
}
документ 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
}
Слил Документы:
{\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
}
просто удаление таблицы шрифтов будет работать, только если оба документа используют один и тот же набор шрифтов. Вам нужно будет однозначно объединить (объединить) таблицы шрифтов (font element wise), если вы хотите сохранить информацию о шрифтах обоих rtfs. Это будет работать для n числа rtfs, но снова нам нужно объединение отдельных таблиц шрифтов.. В настоящее время я работаю над разработкой кода для этого союза, который будет опубликован после его готовности.. :)
в нашем проекте мы также использовали объект Office Doc для визуализации rtfs и выгоды из автоматизации word. Но это создает зависимость от установки ms-word. В частности, это может вызвать проблему, если код должен запускаться с сервера, где память также является проблемой, поскольку использование word API приводит к загрузке экземпляра ms-word в память. Но решение действительно работает!!
хорошо!! Итак, готов с кодом для объединения таблиц шрифтов в двух rtfs и слияния их для сохранения различных шрифтов..Пожалуйста, прочитайте RTFs в строках.
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"));
}
}
}
}
вы можете использовать два текстовых поля. Прочтите rtf-файл в одном текстовом поле (rtbTemp), а затем вырежьте и вставьте текст в другое (rtbMerged). Например:
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;
}
Я думаю, что есть также способ сделать это, не вдаваясь в детали формата RTF. Сохраните RTFs как файлы и используйте автоматизацию MS Word для открытия и добавления документов друг к другу (затем сохраните снова как RTF).
Я использовал этот код два объединить в rtf-файлы, используйте метод de Merge с путем de файлов. Если у вас есть только текст de, вы можете изменить его, но если у вас есть большой документ, вы будете в ошибке памяти. Извините за мой английский.
Я удаляю только 3 charecter из конца первого rtf-файла и один из первых символов второго rtf-файла, и он работает хорошо!
RichTextBox r = new RichTextBox();
r.Rtf = rtf1.Rtf.Substring(0, rtf1.Rtf.Length - 3) + rtf2.Rtf.Substring(1,rtf2.Rtf.Length - 1)