using Microsoft.Reporting.WinForms; using NKC_SDK; using SteamWare; using System; using System.Collections.Generic; using System.Data; using System.Drawing.Imaging; using System.Drawing.Printing; using System.IO; using System.Text; namespace AppData { /// /// Classe che si occupa di stampare report da reportViewer via printer remota /// public class reportPrinter { #region Private Fields private int m_currentPageIndex; /// /// stream del report... /// private IList m_streams; #endregion Private Fields #region Protected Fields /// /// oggetto static/singleton per fare chiamate sul datalayer /// protected DataLayer DLMan = new DataLayer(); protected bool doPdfCopy = false; protected int logLevel = 0; #endregion Protected Fields #region Public Fields /// /// singleton pubblico /// public static reportPrinter obj = new reportPrinter(); #endregion Public Fields #region Protected Constructors /// /// oggetto protected /// /// protected reportPrinter() { logLevel = memLayer.ML.CRI("_logLevel"); doPdfCopy = memLayer.ML.CRB("doPdfCopy"); } #endregion Protected Constructors #region Private Methods /// /// carica i dati richiesti dal report dalla StoredProcedure (filtrando quindi...) /// /// /// cod UDC /// tabella dati private DataTable caricaDati(reportRichiesto tipoReport, string keyParam) { int intIdx = 0; DataTable tab = new DataTable(); // FIXME TODO... string qrCodeBaseUrl = ""; string imagePath = ""; switch (tipoReport) { case reportRichiesto.binPost: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepBin.GetData(intIdx, true, imagePath, qrCodeBaseUrl); break; case reportRichiesto.binPre: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepBin.GetData(intIdx, false, imagePath, qrCodeBaseUrl); break; case reportRichiesto.bunkGroup: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepBunkGroup.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.bunkList: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepBunkList.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.cart: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepCart.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.offline: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepPart.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.part: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepPart.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.cartIRKGroup: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepIRKSum.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.cartIRKList: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepIRK.GetData(intIdx, qrCodeBaseUrl); break; case reportRichiesto.cartSpecParts: int.TryParse(keyParam, out intIdx); tab = (DataTable)DLMan.taRepSpecPart.GetData(intIdx, imagePath, qrCodeBaseUrl); break; default: break; } return tab; } /// /// ciclo da fornire al renderizzatore dei report, per salvare 1 immagine da ogni pagina del report /// /// /// /// /// /// /// private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { // creo files con nomi univoci... string filePathName = string.Format(@"~\temp\{0}_{1:HHmmss}_{1:ffff}.{2}", name, DateTime.Now, fileNameExtension); Stream stream = new FileStream(SteamWare.fileMover.getFilePath(filePathName), FileMode.Create); //Stream stream = new FileStream(SteamWare.SteamwareStrings.getFilePath(@"~\temp\" + name + "." + fileNameExtension), FileMode.Create); m_streams.Add(stream); return stream; } /// /// ciclo da fornire al renderizzatore dei report, per salvare 1 pdf da ogni pagina del report /// /// /// /// /// /// /// private Stream CreateStreamPdf(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { // creo Directory se non c'è SteamWare.fileMover fm = new fileMover(string.Format(@"{0}\{1:yyyy}\{1:MM}\{1:dd}\", memLayer.ML.confReadString("PdfFolder"), DateTime.Now), ""); fm.checkDir(); string pdfPathName = string.Format(@"{0}\{1:yyyy}\{1:MM}\{1:dd}\{2}_{1:HHmmss}_{1:ffff}.{3}", memLayer.ML.confReadString("PdfFolder"), DateTime.Now, name, fileNameExtension); //Stream stream = new FileStream(SteamWare.SteamwareStrings.getFilePath(@"~\temp\" + name + "." + fileNameExtension), FileMode.Create); Stream stream = new FileStream(SteamWare.fileMover.getFilePath(pdfPathName), FileMode.Create); m_streams.Add(stream); return stream; } /// /// esegue print vero e proprio /// /// /// /// private void doEmfPrint(string printerName, LocalReport report, string deviceInfo) { // export in EMF Export(report, deviceInfo); m_currentPageIndex = 0; // stampo Print(printerName); // do dispose? Dispose(); } /// /// effettua stampa in PDF dei vari report in una cartella Anno/Mese/Giorno /// /// /// private void doLocalPdfPrint(LocalReport report, string deviceInfo) { // export in PDF ExportPDF(report, deviceInfo); m_currentPageIndex = 0; // do dispose? Dispose(); } /// /// Export del report come EMF (Enhanced Metafile) file. /// /// private void Export(LocalReport report, string deviceInfo) { Warning[] warnings; m_streams = new List(); report.Render("Image", deviceInfo, CreateStream, out warnings); foreach (Stream stream in m_streams) stream.Position = 0; } /// /// Export del report come PDF file. /// /// private void ExportPDF(LocalReport report, string deviceInfo) { Warning[] warnings; m_streams = new List(); report.Render("PDF", deviceInfo, CreateStreamPdf, out warnings); foreach (Stream stream in m_streams) stream.Position = 0; } /// /// funzione di stampa... /// private void Print(string printerName) { //const string printerName = "Microsoft Office Document Image Writer"; //const string printerName = "Brother HL-2170W series"; if (m_streams == null || m_streams.Count == 0) return; PrintDocument printDoc = new PrintDocument(); printDoc.PrinterSettings.PrinterName = printerName; if (!printDoc.PrinterSettings.IsValid) { Log.Instance.Error(String.Format("Impostazioni non valide per la stampante \"{0}\".", printerName)); return; } printDoc.PrintPage += new PrintPageEventHandler(PrintPage); printDoc.Print(); } /// /// effettua la vera e propria fase di stampa /// /// /// /// /// /// /// private bool printAndLog(string keyParam, string printerName, bool answ, reportRichiesto report, devInfoParam deviceInfo) { try { if (logLevel > 5) Log.Instance.Info(String.Format("Sto per inviare un report alla stampante {0}", printerName)); reportPrinter.obj.printReport(report, printerName, keyParam, deviceInfo); if (logLevel > 5) Log.Instance.Info(String.Format("inviato comando print alla stampante {0}", printerName)); answ = true; } catch (Exception e) { Log.Instance.Error(String.Format("Errore in fase di creazione e stampa report: stampante {0}, errore riscontrato {1}", printerName, e)); } return answ; } /// /// Handler per PrintPageEvents /// /// /// private void PrintPage(object sender, PrintPageEventArgs ev) { Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]); ev.Graphics.DrawImage(pageImage, ev.PageBounds); m_currentPageIndex++; ev.HasMorePages = (m_currentPageIndex < m_streams.Count); } #endregion Private Methods #region Public Methods /// /// dispone l'applicazione e rilascia le risorse /// public void Dispose() { if (m_streams != null) { foreach (Stream stream in m_streams) stream.Close(); m_streams = null; } } /// /// Crea un report locale da file rdlc, carica i dati, esporta report come EMF file e quindi lo invia alla stampante /// /// report ammessi: ElencoMacchine / RichiestaIntervento /// nome completo stampante (rispetto al server) /// cod UDC /// parametri "device input" public void printReport(reportRichiesto tipoReport, string printerName, string keyParam, devInfoParam deviceInfoParam) { LocalReport report = new LocalReport(); report.EnableExternalImages = true; string deviceInfo = ""; string repoBasePath = utils.getPath(memLayer.ML.cdv("ReportBasePath")); string imagePath = memLayer.ML.cdv("ReportImgBasePath"); //"http://seriate.steamware.net:8083/NKC/PartsImg/"; repoBasePath = repoBasePath.Replace("\\site", ""); switch (tipoReport) { case reportRichiesto.binPost: report.ReportPath = string.Format(@"{0}\Bin.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocBin"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.binPre: report.ReportPath = string.Format(@"{0}\Bin.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocBin"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.bunkGroup: report.ReportPath = string.Format(@"{0}\BunkGroup.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocBunkGroup"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.bunkList: report.ReportPath = string.Format(@"{0}\BunkList.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocBunkList"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.cart: report.ReportPath = string.Format(@"{0}\Cart.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocCart"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.cartIRKGroup: report.ReportPath = string.Format(@"{0}\IRK_Kitting_Group.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocIRKGroup"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.cartIRKList: report.ReportPath = string.Format(@"{0}\IRK_Kitting_List.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocIRKList"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.offline: case reportRichiesto.part: report.ReportPath = string.Format(@"{0}\Part.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocPart"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.otherPart: report.ReportPath = string.Format(@"{0}\OtherPart.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocOtherPart"), caricaDati(tipoReport, keyParam))); break; case reportRichiesto.cartSpecParts: report.ReportPath = string.Format(@"{0}\SpecialParts.rdlc", repoBasePath); report.DataSources.Add(new ReportDataSource(memLayer.ML.cdv("ReportDS_DocCartSpecPart"), caricaDati(tipoReport, keyParam))); break; } deviceInfo = deviceInfoParam.xmlParam; doEmfPrint(printerName, report, deviceInfo); // controllo se devo fare copia PDF... stampiamo ANCHE su pdf su una folder locale if (doPdfCopy) { deviceInfoParam.OutputFormat = "PDF"; deviceInfo = deviceInfoParam.xmlParam; doLocalPdfPrint(report, deviceInfo); } } /// /// effettua pulizia della cartella temp x i files più vecchi di X ore (web.config) /// public void pulisciDir() { // num max ore di età x files "vecchi" da tenere in temp area... int maxOre = memLayer.ML.CRI("maxAgeTempAreaHours"); int eliminati = 0; // ottengo elenco files *.emf fileMover.obj.setDirectory(@"~\temp\"); FileInfo[] _fis = fileMover.obj.elencoFiles_FI("*.emf"); bool fatto = false; foreach (FileInfo _file in _fis) { if (_file.CreationTime < DateTime.Now.AddHours(-maxOre)) // elimino files vecchi... { fatto = fileMover.obj.eliminaFile(_file); if (fatto) { Log.Instance.Info(String.Format("Eliminato file {0}", _file.Name)); eliminati++; } } } // salvo il log degli update if (eliminati > 0) { Log.Instance.Info(String.Format("Eliminati {0} files temporanei da area temp", eliminati)); } } /// /// effettua la stampa del cartellino indicato /// /// /// /// indirizzo di rete completo stampante del tipo \\nomePc\nomeStampante, oppure "" x default /// true = si limita ad accodare SENZA stampare /// public bool stampaCartellino(tipoDocumento documento, string keyParam, string printerName, bool queueOnly) { bool answ = false; int idxPrintJob = 0; DataLayer dtProx = new DataLayer(); // gestione coda stampa... // incomincio con gestione della coda di stampa... inserisco in tab la richiesta di stampa... if (memLayer.ML.CRB("disable_singleton")) { dtProx.taPJQ.insertQuery(documento.ToString(), keyParam, printerName); } else { DLMan.taPJQ.insertQuery(documento.ToString(), keyParam, printerName); } if (queueOnly) { answ = true; } else { // faccio un ciclo while... finchè non sono "in testa" alla coda delle esecuzioni aspetto... string nextJob = "ND"; try { if (memLayer.ML.CRB("disable_singleton")) { nextJob = dtProx.taPJQ.getNext()[0].KeyParam; } else { nextJob = DLMan.taPJQ.getNext()[0].KeyParam; } } catch { nextJob = "ND"; } // verifico eventuali processi zombie: quelli in stato 0 con LastTry superiore a data attuale meno zombieMsTime if (memLayer.ML.CRB("disable_singleton")) { dtProx.taPJQ.chiudiZoombie(DateTime.Now.AddMilliseconds(-memLayer.ML.CRI("zombieMsTime"))); } else { DLMan.taPJQ.chiudiZoombie(DateTime.Now.AddMilliseconds(-memLayer.ML.CRI("zombieMsTime"))); } // ora inizio a fare le mie stampe... Random rand = new Random(); int msWait = 200; while (nextJob != keyParam) { // indico che ho fatto un tentativo di stampa aggiornando dtLastTry if (memLayer.ML.CRB("disable_singleton")) { dtProx.taPJQ.updateLastTry(keyParam); } else { DLMan.taPJQ.updateLastTry(keyParam); } // aspetto... msWait = rand.Next(memLayer.ML.confReadInt("minWait"), memLayer.ML.confReadInt("maxWait")); System.Threading.Thread.Sleep(msWait); // leggo prox record da coda if (memLayer.ML.CRB("disable_singleton")) { nextJob = dtProx.taPJQ.getNext()[0].KeyParam; } else { nextJob = DLMan.taPJQ.getNext()[0].KeyParam; } } // salvo idx job... try { if (memLayer.ML.CRB("disable_singleton")) { idxPrintJob = dtProx.taPJQ.getNext()[0].IdxPrintJob; } else { idxPrintJob = DLMan.taPJQ.getNext()[0].IdxPrintJob; } } catch (Exception exc) { Log.Instance.Error($"Errore in recupero IdxPrint Job:{exc}"); } // dimensioni pagina string outForm = ""; string pagWidth = ""; string pagHeigth = ""; string margin = ""; reportRichiesto report = reportRichiesto.bunkGroup; string tipo = ""; switch (documento) { case tipoDocumento.docBinPre: tipo = "docPaint"; report = reportRichiesto.binPre; break; case tipoDocumento.docBinPost: tipo = "docPaintPost"; report = reportRichiesto.binPost; break; case tipoDocumento.docCart: tipo = "docCart"; report = reportRichiesto.cart; break; case tipoDocumento.docCartIRK: tipo = "docCartIRK"; report = reportRichiesto.cartIRKList; break; case tipoDocumento.docCartIRKSum: tipo = "docCartIRKSum"; report = reportRichiesto.cartIRKGroup; break; case tipoDocumento.docPart: tipo = "docPart"; report = reportRichiesto.part; break; case tipoDocumento.docOtherPart: tipo = "docOtherPart"; report = reportRichiesto.otherPart; break; case tipoDocumento.docCartSpecialPart: tipo = "docCartSpecialPart"; report = reportRichiesto.cartSpecParts; break; case tipoDocumento.docStack: tipo = "docStack"; report = reportRichiesto.bunkGroup; break; default: break; } // carico di dati con lettura da web.config parametrica if (string.IsNullOrEmpty(printerName)) { printerName = memLayer.ML.cdv(string.Format("printer{0}", tipo)); } outForm = "EMF"; pagWidth = memLayer.ML.cdv(string.Format("PageWidth{0}", tipo)); pagHeigth = memLayer.ML.cdv(string.Format("PageHeight{0}", tipo)); margin = memLayer.ML.cdv(string.Format("Margin{0}", tipo)); // compongo parametri stampa devInfoParam deviceInfo = new devInfoParam(outForm, pagHeigth, pagWidth, margin, margin, margin, margin); answ = printAndLog(keyParam, printerName, answ, report, deviceInfo); if (answ) { // registro stampato in tabella queue... if (memLayer.ML.CRB("disable_singleton")) { dtProx.taPJQ.updateStato(idxPrintJob, 1); } else { DLMan.taPJQ.updateStato(idxPrintJob, 1); } } else { // registro annullato in tab queue... if (memLayer.ML.CRB("disable_singleton")) { dtProx.taPJQ.updateStato(idxPrintJob, -1); } else { DLMan.taPJQ.updateStato(idxPrintJob, -1); } } } return answ; } #endregion Public Methods } }