viernes, 17 de abril de 2009

Como unir 2 documentos RTF (ASP.NET C#).

Por necesidades del proyecto actual hemos tenido que trabajar con RFT, ya que no podíamos usar las dll de Word. En algunos foros recomiendan no utilizarlas y además en el servidor donde colocaremos la aplicación no podíamos instalar el office.

Generábamos varios documentos, que queríamos unir en uno sólo según la plantilla que usábamos. No hemos acabábamos de encontrar una satisfactoria a la complejidad de nuestros RTF’s.

Por ejemplo, usar el RichTextBox de (de Windows.Forms) como sugerían en algunos foros
, funciona bastante bien, incluso si trabajas con Web, aunque necesitas añadir la referencia. Pero en nuestro caso los ficheros son demasiado complejos y me imagino que si trabajamos con muchos documentos debe dar problemas de memoria.

Finalmente mirando una solución de codeproject
y con alguna sútil y leve pista hemos llegado a una conclusión que nos funciona. En el primer link hay toda una solución para tratar RTF’s, a mí no me ha acabado de funcionar porque la solución no es reconocida por mi versión de Visual Studio, y además me daba algunos errores de código. De todas formas me ha ayudado echarle un ojo, aunque me temo que sobretodo debe funcionar uniendo los RTF's generados por el mismo programa.

Finalmente aquí el código:


using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;




public class RTFUtiles
{
const string cFuentes = "{\\fonttbl";
const string cColores = "{\\colortbl";
const string cHojaEstilos = "{\\stylesheet";
const string cAlmacen = @"{\*\datastore";
const string cEstilosLatentes = @"{\*\latentstyles";
public RTFUtiles()
{
//
//
}
///


/// Une dos documentos RTF.
///

/// Ruta del fichero al que vamos a a¤adir.
/// Ruta del fichero que queremos a¤adir.
public static void Merge(string pRtfPrincipalPath, string pRtfAnyadirPath)
{
if (System.IO.File.Exists(pRtfPrincipalPath))
{
string pPathProvisional = pRtfPrincipalPath.Replace(".rtf", "PROV.rtf");
System.IO.StreamWriter sw = new System.IO.StreamWriter(pPathProvisional, true, System.Text.Encoding.Default);
using (System.IO.StreamReader sr = new System.IO.StreamReader(pRtfPrincipalPath, System.Text.Encoding.Default))
{
// Escribimos el mensaje principal. Sin el final "}}".
string line;
while ((line = sr.ReadLine()) != null)
{
string miLinea = line;
if (sr.EndOfStream)
{
// Quitamos el final "}}".
miLinea = miLinea.TrimEnd().Substring(0, (miLinea.Length - 1));
}
sw.WriteLine(miLinea);
sw.Flush();
}
}
// Nueva p gina
sw.WriteLine("\\page");
sw.Flush();
// A¤adimos el contenido del segundo sin incio, definici¢n de colores y fuentes.
System.IO.StreamReader sr2 = new System.IO.StreamReader(pRtfAnyadirPath, System.Text.Encoding.Default);
string texto2 = sr2.ReadToEnd();
sr2.Close();
sw.WriteLine(Contenido(texto2.Trim()));
sw.Flush();
// A¤adimos el final de documento que hemos quitado al primero.
sw.WriteLine("}");
sw.Flush();
sw.Close();
// Reemplazamos el fichero para que sea el mismo que el original.
System.IO.File.Copy(pPathProvisional, pRtfPrincipalPath, true);
System.IO.File.Delete(pPathProvisional);
}
else
{
System.IO.File.Copy(pRtfAnyadirPath, pRtfPrincipalPath);
}
}
private static string Contenido(string pRtf)
{
string wRt = pRtf;
wRt = wRt.Replace(Inicio(wRt), "");
wRt = wRt.Replace(Colores(wRt), "");
wRt = wRt.Replace(Fuentes(wRt), "");
wRt = wRt.Replace(HojaEstilos(wRt), "");
wRt = wRt.Replace(Almacen(wRt), "");
wRt = wRt.Replace(EstilosLatentes(wRt), "");
wRt = wRt.Substring(0, (wRt.Length - 1));
return wRt;
}
private static string Fuentes(string pRtf)
{
return BuscarTag(pRtf, cFuentes);
}

private static string Colores(string pRtf)
{
return BuscarTag(pRtf, cColores);
}
private static string HojaEstilos(string pRtf)
{
return BuscarTag(pRtf, cHojaEstilos);
}
private static string Almacen(string pRtf)
{
return BuscarTag(pRtf, cAlmacen);
}
private static string EstilosLatentes(string pRtf)
{
return BuscarTag(pRtf, cEstilosLatentes);
}


private static string Inicio(string pRtf)
{
string wRt = string.Empty;
int intFuente = 0;
char[] rtfCh = pRtf.ToCharArray();
int pos = 0;
for (int i = intFuente; i < pRtf.Length; i++)
{
if (rtfCh[i] == char.Parse("{"))
{
pos++;
}
if (rtfCh[i] == char.Parse("}"))
{
pos--;
}
if (pos == 2)
{
return wRt;
}
wRt += rtfCh[i].ToString();
}
return wRt;
}
private static string BuscarTag(string pRtf, string pTag)
{
string wRt = string.Empty;
int intFuente = pRtf.IndexOf(pTag);
char[] rtfCh = pRtf.ToCharArray();
try
{
if (intFuente < 0) { intFuente = 0; }
int pos = 0;
for (int i = intFuente; i < rtfCh.Length; i++)
{
wRt += rtfCh[i].ToString();
if (rtfCh[i] == char.Parse("{"))
{
pos++;
}
if (rtfCh[i] == char.Parse("}"))
{
pos--;
}
if (pos == 0)
{
return wRt;
}
}
}
catch (Exception pErr)
{
throw pErr;
}
return wRt;
}
}

2 comentarios:

  1. El código me había quedado cortado, lo he rectificado.

    ResponderEliminar
  2. Hola chico! Por favor, eche un vistazo a mi código en el siguiente enlace http://anhleduc.blogspot.com/2011/02/trick-of-processing-rtf-files.html

    ResponderEliminar