--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.
Hola a todos,
Trabajando con ficheros PDF y .NET (C#) no es trivial y hay que llegar al detalle de lo que realmente se quiere implementar. Alternativas hay muchas como librerías ITextsharp o PDfSharp, pasando por Ghostscript, y hasta Crystal Report y ReportViewer de Microsoft.
Por si fuera útil , expongo diversas estrategias y experiencias, agradecería también que compartáis comentarios y mismas experiencias.
Código HTML a PDF
éste de codeproject:
http://www.codeproject.com/KB/aspnet/HTML2PDF.aspx
http://www.codeproject.com/KB/cs/Easy_PDF_Programming.aspx
Luego ya productos de terceros de pago, hay muchos:
http://www.codeproject.com/KB/showcase/TallComponents.aspx
If you Html is XHtml you can use PDFizer to do the job.
http://sourceforge.net/projects/pdfizer/
PDF en una aplicación Web ASP.NET 4.0
mostrar sólo la primera página de un PDF en ASP.NET
“Para generar vistas previas de archivos pdf, podrías utilizar Magick.Net que es un wrapper de ImageMaick para .Net, y existen ejemplos en el sitio de documentación de Magick.Net para hacer lo que necesitas (solamente hay que tener cuidado de tener instalado Ghostscript y que la plataforma en el que instalas Ghostscript sea la misma que la libreria que tenes en tu proyecto x86 o x64).”
Otras opciones: “Generando el PDF en Crystal Report (http://www.gabrielortiz.com/descargas/Manual_Crystal_Reports_XI.pdf) y enviándolo al cliente en ese formato (pdf)”
Una alternativa a Crystal es usar ReportViewer de Microsoft, que es menos potente pero tiene la ventaja de que el despliegue es algo más sencillo y el instalador ocupa menos. Tienes más info aquí: http://msdn.microsoft.com/en-us/library/ms251671%28v=vs.100%29.aspx
Diversas experiencias:
MAJimenez
“
Utiliza un wrapper para la dll de GhostScript, lee los pdf, extrae una imagen de la primera hoja y que te cree el thumbnail y la almacenas en tu filesystem o en una db:
http://www.mattephraim.com/blog/2009/01/06/a-simple-c-wrapper-for-ghostscript/
Yo utilizo esta configuracion para crear thumbnails en escala de grises:
private static string[] GetArgsSalidaThumbsJpg(string inputPath, string outputPath)
{
return new[]
{
"PdftoJpg",
"-q",
"-dQUIET",
"-dPARANOIDSAFER",
"-dBATCH",
"-dNOPAUSE",
"-dNOPROMPT",
"-dMaxBitmap=500000000",
"-dEPSCrop",
"-dAlignToPixels=0",
"-dGridFitTT=0",
"-sDEVICE=jpeggray",
"-dTextAlphaBits=4",
"-dGraphicsAlphaBits=4",
"-r11",
String.Format("-sOutputFile={0}", outputPath),
inputPath
};
}
Estuve utilizando una clase que servia como wrapper que se llama GhostscriptSharp.cs, nada mas seria que la buscaras en google y la integras en tu codigo.”
Walter Poch
“Lo que yo terminé usando es iTextSharp con templates en PDF, entonces defino campos dinámicos en las templates PDF que luego lleno por código. Algo así:
public virtual void ImprimirComprobante(long turnoId)
{
var turno = SessionFactory.GetCurrentSession().Load<Turno>(turnoId);
//Valido que sea del paciente actual
if (turno.Paciente.Id != User.As<Paciente>().Id)
throw new SecurityException("El usuario actual no es al que se le otorgó el turno.");
// Read the template
var reader = new PdfReader(Server.MapPath("~/Reports/ComprobanteTurno.pdf"));
// Writes the modified template to http response
this.HttpContext.Response.Clear();
this.HttpContext.Response.ContentType = "application/pdf";
var stamper = new PdfStamper(reader, this.HttpContext.Response.OutputStream);
// Retrieve the PDF form fields defined in the template
var form = stamper.AcroFields;
// Set values for the fields
form.SetField("Fecha", turno.FechaTurno.ToString());
form.SetField("Profesional", turno.Profesional.Persona.NombreCompleto);
form.SetField("Especialidad", turno.Especialidad.Nombre);
form.SetField("Paciente", turno.Paciente.Persona.NombreCompleto);
form.SetField("Consultorio", turno.Consultorio.Nombre);
// Setting this to true to make the document read-only
stamper.FormFlattening = true;
//Close the stamper instance
stamper.Close();
}
De esa forma evito tener que
"diseñar" con iTextSharp. Pero no sirve para listados más que para la
cabecera.”
Claudio Meschini
“
El problema principal que tiene .rdlc para
trabajar con los objetos del dominio directamente es que no soporta jerarquias
de objetos, entonces para imprimir una factura con detalles tenes que armar un
mapper donde aplanes por ejemplo el objeto factura completo.
Este
codigo trabaja con una clase ReportInfo que es un dto que usamos para pasarle
al servicio los parametros del reporte.
Fijate
que hay un thread de la lista donde se discutio un poco el tema, el subject era "Reportes e impresión desde proyecto web asp.net mvc 3". Ahí Leo Micheloni comento sobre un error de .rdlc: http://leomicheloni.blogspot.com.ar/2010/05/error-poco-descriptivo-en-microsoft.html
Fijate en
este link tambien por el tema de los device info: http://msdn2.microsoft.com/en-us/library/ms155397.aspx
Y acá
para su uso con MVC: http://weblogs.asp.net/rajbk/archive/2009/11/25/rendering-an-rdlc-directly-to-the-response-stream-in-asp-net-mvc.aspx
Un último
tema muy importante: para poder usar el editor de .rdlc con MVC tenes que tener
en VS20xx abierta una página .aspx (sic)
using System;
using
System.Web;
using
System.Collections.Generic;
using
Microsoft.Reporting.WebForms;
namespace
TuNamespace
{
public class ServiceReport
{
private static List<ReportInfo> _reports = new List<ReportInfo>();
private static string dirCsv = System.Web.HttpContext.Current.Server.MapPath(@"~\CSV");
public Dictionary<string, string> typesMime = new Dictionary<string,
string>();
private const string PathReports = "~/Content/Reports/";
private const string FileExtensionReports = "rdlc";
public ServiceReport()
{
typesMime.Add("pdf", "application/pdf");
typesMime.Add("csv", "text/csv");
}
public byte[] BuildReport(ReportInfo reportInfo, string typeOutput)
{
LocalReport localReport = new LocalReport();
localReport.ReportPath = HttpContext.Current.Server.MapPath(String.Format("{0}{1}.{2}",
PathReports, reportInfo.Key, FileExtensionReports)); //
"~/Content/Reports/CustomerReport.rdlc");
ReportDataSource reportDataSource = new ReportDataSource(reportInfo.NameDataSource,
reportInfo.DataSource);
localReport.DataSources.Add(reportDataSource);
string reportType = typeOutput.ToUpper();
string mimeType;
string encoding;
string fileNameExtension;
//The DeviceInfo settings should be changed based on the reportType
//http://msdn2.microsoft.com/en-us/library/ms155397.aspx
string deviceInfoPdf =
"<DeviceInfo>" +
" <OutputFormat>PDF</OutputFormat>"
+
" <PageWidth>8.5in</PageWidth>" +
" <PageHeight>11in</PageHeight>" +
" <MarginTop>0.5in</MarginTop>" +
" <MarginLeft>1in</MarginLeft>" +
" <MarginRight>1in</MarginRight>"
+
" <MarginBottom>0.5in</MarginBottom>"
+
"</DeviceInfo>";
string deviceInfoCsv =
"<DeviceInfo>" +
" <OutputFormat>CSV</OutputFormat>"
+
"<Encoding>UTF-8</Encoding>" +
"<ExcelMode>true</ExcelMode>" +
"</DeviceInfo>";
string deviceInfo;
if (typeOutput.ToUpper() == "PDF")
deviceInfo = deviceInfoPdf;
else
deviceInfo = deviceInfoCsv;
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
//Render the report
return localReport.Render(reportType, deviceInfo, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
}
}
}
using
System;
namespace
TuNamespace
{
public class ReportInfo
{
public ReportInfo(string key, string title, string description,
Func<object> getDataSource)
{
Key = key;
Title = title;
Description = description;
GetDataSources = getDataSource;
NameDataSource = key;
}
public string Key { get; private set; }
public string Title { get; private set; }
public string Description { get; private set; }
public object DataSource
{
get
{
return GetDataSources.Invoke();
}
}
public string NameDataSource { get; set; }
private Func<object> GetDataSources { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj.GetType() == typeof(ReportInfo))
return ((ReportInfo)obj).Key == this.Key;
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}”
Librerías de referencia:
Una clase helper , buscando en github
PDFSharp
http://www.pdfsharp.net/Downloads.ashx
“Existe una librería para trabajar con pdf´s liberada bajo la licencia MIT, la librería permite crear y producir pdfs desde código C# a si como otras opciones como rellenar pdfs de la declaración de la renta desde código. Los ejemplos, que os adjunto, son para concatenar varios pdfs, un proyecto los concatena una hoja por folio y el segundo dos hojas por folio.”
Otros productos (con licencia) como, PdfLib es potente
http://www.pdflib.com/products/
http://www.pdflib.com/products/pdflib-family/pdflib/
O los productos de Aspose para PDF
http://www.aspose.com/.net/pdf-component.aspx
Proyectos Open Source en C#
Espero que alguien le resulte útil.
Yo he terminado usando Microsoft Reporting Services con local reports tal como plantea Cláudio en el mail superior.
El tema es el bug que tiene para que te tome los objetos de dominio en mvc que hay que agregar una página .aspx al proyecto, no se si lo habrán resuelto en la nuevas versiones.
<p class="MsoNormal" style="background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; bac
Diversas experiencias de un compañero, para imprimir en forma batch una serie de documentos (facturas en PDF) desde una aplicación ASP.NET.
Con el comando Shell "print" e indicando la impresora no funcionaba. Finalmente, con una llamada de a través de un proceso de la shell pero en lugar de al Acrobat Reader con Ghostscript
public class GSInterface
{
public string GhostScriptExePath { get; private set; }
public GSInterface(string gsExePath)
{
this.GhostScriptExePath = gsExePath;
}
public virtual void CallGhostScript(string[] args)
{
System.IO.StreamReader sError = null;
System.IO.StreamReader sOut = null;
Process p = new Process();
p.StartInfo.FileName = this.GhostScriptExePath;
p.StartInfo.Arguments = string.Join(" ", args);
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
if (ConfigurationManager.AppSettings["pruebas"].ToString() == "S")
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
}
p.Start();
p.WaitForExit();
if (ConfigurationManager.AppSettings["pruebas"].ToString() == "S")
{
sError = p.StandardError;
sOut = p.StandardOutput;
if (sError.ReadToEnd().Trim() != "")
{
System.IO.TextWriter fich = null;
fich = System.IO.File.CreateText(@"c:\tmp\error_" + System.DateTime.Now.Ticks.ToString() + ".txt");
fich.WriteLine("resultado:" + sOut.ReadToEnd().Trim());
fich.WriteLine("error:" + sError.ReadToEnd().Trim());
}
}
}
public void Print(string filename, string printerName)
{
this.CallGhostScript(new string[] {
"-q",
"-sDEVICE=mswinpr2",
"-sPAPERSIZE=a4",
"-dNOPAUSE",
"-dNoCancel",
"-dBATCH",
"-dDuplex",
string.Format(@"-sOutputFile=""\\spool\{0}""", printerName),
string.Format(@"""{0}""", filename)
});
}
}
Luego la invoco de esta manera:
string printerName = ConfigurationManager.AppSettings["impresora"].ToString();
GSInterface gs = new GSInterface(ConfigurationManager.AppSettings["rutaGS"].ToString());
gs.Print(sRutaFacturas + sNombrePDFFacturaSocio, printerName);