martedì 10 novembre 2009

Translator English Italian

ASP.net: convertire file Excel in PDF

Mi è capitato di dover convertire dei file excel, uplodati su una applicazione ASP dagli utenti, in formato PDF. Dopo alcuni tentativi, nei quali ho cercando di utilizzare stampanti PDF come winPDF, ho deciso di utilizzare direttamente excel 2007. Infatti la versione 2007 ha di per sè la capacità di salvare documenti in formato PDF. Basta installare un add-in scaricabile a questo indirizzo. La soluzione prevede però l'istallazione di excel 2007 sul server web dove risiede l'applicazione (cosa fortemente sconsigliata da Microsoft ma che semplifica la vita e che consiglio se, come nel mio caso, si tratta di una applicazione intranet).
Vediamo più in dettaglio cosa bisogna fare!

Per la conversione di formato è necessario utilizzare le librerie Microsoft.Office.Interop.Excel messe a disposizione da Office. Utilizzando queste è sufficiente caricare il file excel a livello applicativo e salvarlo con l'altro formato (save as).

using Excel = Microsoft.Office.Interop.Excel;

....

public static string ConvertExcelFileToPDF(String filename, String filePath)
{
String newPdfFilename = null;
using (new SwitchCulture())
{
Excel.ApplicationClass excelApplication = null;
Excel.Workbook excelWorkBook = null;
object missing = Type.Missing;

Excel.XlFixedFormatType paramExportFormat = Excel.XlFixedFormatType.xlTypePDF;
Excel.XlFixedFormatQuality paramExportQuality = Excel.XlFixedFormatQuality.xlQualityStandard;
bool paramOpenAfterPublish = false;
bool paramIncludeDocProps = false;
bool paramIgnorePrintAreas = false;
object paramFromPage = Type.Missing;
object paramToPage = Type.Missing;

try
{
newPdfFilename = filename + ".pdf";
HttpServerUtility Server = HttpContext.Current.Server;
string excelFileNamePath = Server.MapPath(filePath + "/" + filename);
string pdfFileNamePath = Server.MapPath(filePath + "/" + newPdfFilename);

excelApplication = new Excel.ApplicationClass();

// Open the source workbook.
excelWorkBook = excelApplication.Workbooks.Open(excelFileNamePath,
missing, missing, missing, missing,
missing, missing, missing, missing,
missing, missing, missing, missing,
missing, missing);


// Save it in the target format.
if (excelWorkBook != null)
excelWorkBook.ExportAsFixedFormat(paramExportFormat,
pdfFileNamePath, paramExportQuality,
paramIncludeDocProps, paramIgnorePrintAreas, paramFromPage,
paramToPage, paramOpenAfterPublish,
missing);

}
catch (Exception ex)
{
LogFactory.Logger.WriteLog(ex);
}
finally
{
// Close the workbook object.
if (excelWorkBook != null)
{
excelWorkBook.Close(false, missing, missing);
excelWorkBook = null;
}

// Quit Excel and release the ApplicationClass object.
if (excelApplication != null)
{
excelApplication.Quit();
excelApplication = null;
}

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
return newPdfFilename;
}


E' di importanza fondamentale utilizzare la classe SwitchCulture a causa di un bug delle librerie office. Infatti se si utilizza una versione inglese di Excel ma i regional settings del server sono settati su una lingua diversa si ottiene il seguente errore:
"Old format or invalid type library. (Exception from HRESULT: 0x80028018 (TYPE_E_INVDATAREAD))"
o
"Formato vecchio o libreria di tipo non valido. (Exception from HRESULT: 0x80028018 (TYPE_E_INVDATAREAD))"
Questa classe non fà altro che cambiare la culture del thread corrente a inglese facendo funzionare correttamente Excel.

public class SwitchCulture : IDisposable
{
private CultureInfo originalCulture = null;

public SwitchCulture()
{
originalCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
//Thread.CurrentThread.CurrentCulture = new CultureInfo("it-IT");
}

public void Dispose()
{
Thread.CurrentThread.CurrentCulture = originalCulture;
}
}


UPDATE 14.05.2010

Vi segnalo alcuni riferimenti per approfondire l'argomento:
Culture BUG
Excel Tasks
Saving Workbooks to PDF and XPS Formats in Excel 2007

2 commenti:

Anonimo ha detto...

Probabilmente qualcuno ti ha dato una mano sulla soluzione del problema.... :D

Emonkey ha detto...

Si, per la risoluzione di questo problema, abbiamo usato un DUAL-CORE!
;)

Posta un commento