public SignallingResult SendSignal(ShermMessage signal)
        {
            var result = SignallingResult.Timeout;

            try
            {
                IpcClientPipe cli = new IpcClientPipe(".", signal.Pipename);
                using (var pipe = cli.Connect(100))
                {
                    result = core.intercom.SignallingResult.Failure;
                    /* send data to the server */
                    var serialized_message = MessageSerializers.SerializeMessage(signal);
                    if (serialized_message.Length > NamedPipeIpcServer.SERVER_IN_BUFFER_SIZE)
                    {
                        throw new ArgumentOutOfRangeException("serialized_message.Length", serialized_message.Length, NamedPipeIpcServer.SERVER_IN_BUFFER_SIZE.ToString());
                    }
                    pipe.Write(serialized_message, 0, serialized_message.Length);
                    /* read the result */
                    var   data      = new Byte[NamedPipeIpcServer.SERVER_OUT_BUFFER_SIZE];
                    Int32 bytesRead = pipe.Read(data, 0, data.Length);
                    Tracing.VerboseBkg("Server response: " + Encoding.UTF8.GetString(data, 0, bytesRead));
                    /* done with this one */
                    pipe.Close();
                    /* succeeded */
                    result = SignallingResult.OK;
                }
            }
            catch (Exception ex)
            {
                Tracing.ErrorBkg("Named pipe connection failed: {0}", ex.ToString());
            }
            return(result);
        }
示例#2
0
        /// <summary>
        /// Makes a PDF file representing the filled-in Czech "Zaznam o urazu" form
        /// </summary>
        public bool Render(string rpt_temp_path, Stream docstream)
        {
            OnProgress(ReportProgressIndicator.I3_GeneratingContent, 0, 30, null);
            DateTime     nowtime              = DateTime.UtcNow;
            const string temp_file_naming     = "sherm-zaznamourazu-temp-pdf-template-{0}.pdf";
            const string result_file_naming   = "sherm-zaznamourazu-{0}.pdf";
            string       temp_file_name       = String.Format(temp_file_naming, nowtime.ToString("yyyyMMddHHmmss"));
            string       result_file_name     = String.Format(result_file_naming, nowtime.ToString("yyyyMMddHHmmss"), this.GetResultFileExtension());
            string       templateResourcePath = GetTemplateResourcePath();

            try
            {
                string tempPath         = rpt_temp_path; /* [dlatikay 20120820] we do not bother the system, we have our own: was: Path.GetTempPath(); */
                string temp_file_path   = Path.Combine(tempPath, temp_file_name);
                string result_file_path = Path.Combine(tempPath, result_file_name);
                /* 1. open the template */
                OnProgress(ReportProgressIndicator.I3_GeneratingContent, 10, 31, OnLiteral(3137)); /* Loading template */
                using (var t_template = new System.IO.BinaryReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(templateResourcePath)))
                {
                    /* 1a. we must persist it in the temporary files folder */
                    using (var os = new FileStream(temp_file_path, FileMode.Create, FileAccess.Write))
                    {
                        using (var t_template_wr = new BinaryWriter(os))
                        {
                            byte[] temppdfcontent = t_template.ReadBytes((int)t_template.BaseStream.Length);
                            t_template_wr.Write(temppdfcontent);
                        }
                    }
                }
                /* remove the read-only attribute */
                var attr = File.GetAttributes(temp_file_path);
                attr &= ~FileAttributes.ReadOnly;                 /* lovely */
                File.SetAttributes(temp_file_path, attr);
                /* 1b. get us an instance of good old itextsharp and open the template */
                OnProgress(ReportProgressIndicator.I3_GeneratingContent, 20, 32, OnLiteral(3138)); /* Starting word processor */
                try
                {
                    var pdfReader = new sherm.text.portable.PdfReader(temp_file_path);
                    using (var result_fs = new FileStream(result_file_path, FileMode.Create))
                    {
                        var pdfStamper = new sherm.text.portable.PdfStamper(pdfReader, docprop_product, docprop_revision, docprop_version, result_fs);
                        /* now its time to set all the bookmarks */
                        OnProgress(ReportProgressIndicator.I3_GeneratingContent, 40, 34, OnLiteral(3140)); /* Completing the form */
                        var pdfFields = pdfStamper.AcroFields;
                        //var states = pdfFields.GetAppearanceStates("r6");
                        //foreach (var fld in pdfFields.Fields)
                        //    Debug.WriteLine(fld.Key);

                        /* in order to be able to render the czech characters, we need to do some magic according to:
                         * http://stackoverflow.com/questions/15089291/how-to-use-utf-8-encoding-in-itextsharp-pdf-stamper
                         * and
                         * http://www.mikesdotnetting.com/Article/81/iTextSharp-Working-with-Fonts */
                        var      fontfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "arial.ttf");
                        BaseFont bfHelvetica;
                        try
                        {
                            bfHelvetica = BaseFont.CreateFont(fontfile, BaseFont.IDENTITY_H, BaseFont.EMBEDDED); /* microsoft's helvetica is arial :-) */
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(String.Format("Failed to create substitution font from \"{0}\": {1}", fontfile, ex.Message), ex);
                        }
                        pdfStamper.AcroFields.AddSubstitutionFont(bfHelvetica);
                        pdfFields.SetField("ecZaznamu", zou_IdNumber_Accident);
                        pdfFields.SetField("ecZamestnavatele", zou_IdNumber_Employer);
                        if (zou_AccidentType_Fatality)
                        {
                            pdfFields.SetField("typUrazu", "1");
                        }
                        else if (zou_AccidentType_Hospitalization)
                        {
                            pdfFields.SetField("typUrazu", "2");
                        }
                        else if (zou_AccidentType_Other)
                        {
                            pdfFields.SetField("typUrazu", "3");
                        }
                        pdfFields.SetField("fill_2", zou_A_LegalEmployer_BusinessSector);
                        pdfFields.SetField("fill_1", zou_A_LegalEmployer_NameAndAddress);
                        pdfFields.SetField("fill_3", zou_A_LegalEmployer_PlaceOfAccident);
                        if (zou_A_RegularOccupationalAccident_Yes)
                        {
                            pdfFields.SetField("pravidelnePracoviste", "1");
                        }
                        else if (zou_A_RegularOccupationalAccidentNo)
                        {
                            pdfFields.SetField("pravidelnePracoviste", "0");
                        }
                        pdfFields.SetField("ico", zou_B_Worksiteemployer_IdNumber);
                        pdfFields.SetField("fill_5", zou_B_Worksiteemployer_BusinessSector);
                        pdfFields.SetField("fill_4", zou_B_Worksiteemployer_NameAndAddress);
                        pdfFields.SetField("fill_6", zou_B_Worksiteemployer_PlaceOfAccident);
                        pdfFields.SetField("1 Jméno", zou_C_Victimname);
                        pdfFields.SetField("2 Datum narození", zou_C_VictimDoB);
                        if (zou_C_Victimgender_Male)
                        {
                            pdfFields.SetField("pohlavi", "1");
                        }
                        else if (zou_C_Victimgender_Female)
                        {
                            pdfFields.SetField("pohlavi", "2");
                        }
                        pdfFields.SetField("fill_10", zou_C_VictimNationality);
                        pdfFields.SetField("4 Druh práce KZAM", zou_C_TypeOfWorkISCO);
                        pdfFields.SetField("fill_12", zou_C_Activity);
                        pdfFields.SetField("roku", zou_C_Year.ToString());
                        pdfFields.SetField("mesicu", zou_C_Monthname);
                        if (zou_C_VictimIsRegularEmployee)
                        {
                            pdfFields.SetField("urazemPostizeny", "1");
                        }
                        else if (zou_C_VictimIsContractor)
                        {
                            pdfFields.SetField("urazemPostizeny", "2");
                        }
                        else if (zou_C_VictimIsParagraph12)
                        {
                            pdfFields.SetField("urazemPostizeny", "3");
                        }
                        else if (zou_C_VictimIsLearning)
                        {
                            pdfFields.SetField("urazemPostizeny", "4");
                        }
                        pdfFields.SetField("neschopnostOd", zou_C_VictimAbsentFrom);
                        pdfFields.SetField("neschopnostDo", zou_C_VictimAbsentTo);
                        pdfFields.SetField("celkemKalendardnichDnu", zou_C_AbsentCalendardays);
                        pdfFields.SetField("datumUrazu", zou_D_EventDatetimeDate);
                        pdfFields.SetField("hodinaUrazu", zou_D_EventDatetimeHour);
                        pdfFields.SetField("fill_3_2", zou_D_WorktimePriorToAccident);
                        pdfFields.SetField("datumUmrti", zou_D_DateOfDeath);
                        pdfFields.SetField("fill_4_2", zou_D_WorktimePriorToAccident);
                        pdfFields.SetField("fill_5_2", zou_D_Bodypart);
                        pdfFields.SetField("fill_6_2", zou_D_TotalNumberOfInjuredPersons);
                        /* medium */
                        if (zou_D_InjuringMedium_Vehicle)
                        {
                            pdfFields.SetField("r6", "1");
                        }
                        else if (zou_D_InjuringMedium_MovingParts)
                        {
                            pdfFields.SetField("r6", "2");
                        }
                        else if (zou_D_InjuringMedium_Material)
                        {
                            pdfFields.SetField("r6", "3");
                        }
                        else if (zou_D_InjuringMedium_Falling)
                        {
                            pdfFields.SetField("r6", "4");
                        }
                        else if (zou_D_InjuringMedium_Equipment)
                        {
                            pdfFields.SetField("r6", "5");
                        }
                        else if (zou_D_InjuringMedium_HarmfulSubstance)
                        {
                            pdfFields.SetField("r6", "6");
                        }
                        else if (zou_D_InjuringMedium_Heat)
                        {
                            pdfFields.SetField("r6", "7");
                        }
                        else if (zou_D_InjuringMedium_StationaryMachinery)
                        {
                            pdfFields.SetField("r6", "8");
                        }
                        else if (zou_D_InjuringMedium_HumanAnimalNature)
                        {
                            pdfFields.SetField("r6", "9");
                        }
                        else if (zou_D_InjuringMedium_Electricity)
                        {
                            pdfFields.SetField("r6", "10");
                        }
                        else if (zou_D_InjuringMedium_Other)
                        {
                            pdfFields.SetField("r6", "11");
                        }
                        /* cause */
                        if (zou_D_Cause_InadequateUseOrCondition)
                        {
                            pdfFields.SetField("r7", "1");
                        }
                        else if (zou_D_Cause_InadequateAssessment)
                        {
                            pdfFields.SetField("r7", "2");
                        }
                        else if (zou_D_Cause_WorkplaceShortcomings)
                        {
                            pdfFields.SetField("r7", "3");
                        }
                        else if (zou_D_Cause_PPE)
                        {
                            pdfFields.SetField("r7", "4");
                        }
                        else if (zou_D_Cause_RulesAndRegulations)
                        {
                            pdfFields.SetField("r7", "5");
                        }
                        else if (zou_D_Cause_VisMajor)
                        {
                            pdfFields.SetField("r7", "6");
                        }
                        else if (zou_D_Cause_Other)
                        {
                            pdfFields.SetField("r7", "7");
                        }
                        /* remainder */
                        pdfFields.SetField("fill_1_2", zou_D_UnderInfluence);
                        pdfFields.SetField("fill_1_3", zou_D_CourseOfEvents);
                        pdfFields.SetField("fill_3_3", zou_D_RulesAndRegulations);
                        pdfFields.SetField("fill_4_3", zou_D_Measures);
                        pdfFields.SetField("undefined_5", zou_E_Description);
                        pdfFields.SetField("datum jméno a podpis", zou_E_DateNameOfVictim);
                        pdfFields.SetField("datum jméno a podpis_2", zou_E_DateNameOfWitness1);
                        pdfFields.SetField("datum jméno a podpis_3", zou_E_DateNameOfWitness2);
                        pdfFields.SetField("datum jméno a podpis_4", zou_E_DateNameOfWitness3);
                        pdfFields.SetField("datum jméno a podpis_5", zou_E_DateNameOfHSRepresentative);
                        pdfFields.SetField("datum jméno a podpis_6", zou_E_DateNameOfEmployeeRepresentative);
                        pdfFields.SetField("datum jméno a podpis_7", zou_E_DateNameOfEmployerRepresentative);
                        pdfFields.SetField("pracovniZarazeni", zou_E_EmployeeFunctionPosition);
                        /* protect and save */
                        OnProgress(ReportProgressIndicator.I3_GeneratingContent, 70, 35, OnLiteral(3141)); /* Saving completed form */
                        //pdfStamper.FormFlattening = true; /* may not flatten; would impair substitution font for unicode */
                        pdfStamper.Close();
                        /* persist it */
                    }
                }
                catch (Exception ei1)
                {
                    /* up the exception chain */
                    Tracing.ErrorBkg(ei1.ToString());
                    throw new Exception("An error occurred whilst portable document stamping was in progress.", ei1);
                }
                /* now we load the document into memory and deliver the stream. the file is deleted. */
                OnProgress(ReportProgressIndicator.I3_GeneratingContent, 90, 38, OnLiteral(3143)); /* Uploading document to database */
                using (FileStream ifs = new FileStream(result_file_path.ToString(), FileMode.Open, FileAccess.Read))
                {
                    using (var rd = new BinaryReader(ifs))
                    {
                        docstream.Write(rd.ReadBytes((int)rd.BaseStream.Length), 0, (int)rd.BaseStream.Length);
                        rd.Close();
                        docstream.Seek(0, SeekOrigin.Begin);
                    }
                }
                OnProgress(ReportProgressIndicator.I3_GeneratingContent, 100, 39, OnLiteral(3144)); /* Deleting temporary files */
                OnProgress(ReportProgressIndicator.I5_GeneratedContent, 0, 39, null);
                File.Delete(temp_file_path);
                File.Delete(result_file_path.ToString());
                OnProgress(ReportProgressIndicator.I5_GeneratedContent, 100, 40, null);
                /* succeeded */
                return(true);
            }
            catch (Exception ei2)
            {
                /* for debugging purposes */
                Tracing.ErrorBkg(ei2.ToString());
                throw new Exception("An error occurred whilst rendering \"Zaznam o urazu\" document using portable document stamping.", ei2);
            }
        }
示例#3
0
        protected override bool RenderInternal(ref MemoryStream chunk, out string mime)
        {
            mime = null;
            var tmpfilename = String.Format("{0}.xlsx", Guid.NewGuid().ToString());

            try
            {
                /* 1. instantiate the epplus templating engine */
                var template = new FileInfo(Path.Combine(CustomAbsPath, @"2014_10_01_Sofortmeldung_TKMI.xlsx"));
                var dest     = new FileInfo(Path.Combine(RptTmpBasepath, tmpfilename));
                using (var package = new ExcelPackage(dest, template))
                {
                    ExcelWorkbook  wbk = package.Workbook;
                    ExcelWorksheet sht = wbk.Worksheets[1];
                    /* 2. populate the template into the new file */
                    var dt = Data.Tables[ReportDatatableIdentifiers.REPORT_DATATABLE_HARDCOPY_SAFETY_003].Rows[0];
                    wbk.Names["xbusarea"].Value                         = dt["fBusinessUnit"].ToString();
                    wbk.Names["xtitle"].Value                           = this.Caption;
                    wbk.Names["xkonzernunternehmen"].Value              = dt["Companyname"].ToString();
                    wbk.Names["xstandortort"].Value                     = dt["fOperatingUnit"].ToString();
                    wbk.Names["xunfallmelder"].Value                    = dt["fOrgLeaderName"].ToString();
                    wbk.Names["xtelefonrueckfragen"].Value              = dt["fOrgLeaderPhone"].ToString(); /* [pkosec 20141212] MEA-2014-00507.3 */
                    wbk.Names["xunfallkategorie"].Value                 = dt["ReportableTOC"].ToString();
                    wbk.Names["xereignisart"].Value                     = dt["fSeverity"].ToString();
                    wbk.Names["xverunfalltername"].Value                = dt["fAffectedPersonName"].ToString();
                    wbk.Names["chk_verunfallterstammpersonal"].Value    = dt["fPermanentStaff"].ToString();
                    wbk.Names["chk_verunfallterleiharbeitnehmer"].Value = dt["fLeasedLabour"].ToString();
                    wbk.Names["chk_verunfallterfremdfirma"].Value       = dt["fContractor"].ToString();
                    wbk.Names["chkverunfallterazubi"].Value             = dt["fVictimIsTrainee"].ToString();
                    wbk.Names["xleiharbeitsfirma"].Value                = dt["fLeasedPartnerName"].ToString();
                    wbk.Names["xfremdfirma"].Value                      = dt["fContractorPartnerName"].ToString();
                    wbk.Names["xunfallzeitpunkt"].Value                 = dt["fEventDate"].ToString();
                    wbk.Names["xunfalluhrzeit"].Value                   = dt["fEventTime"].ToString();
                    wbk.Names["xunfallort"].Value                       = dt["fLocation"].ToString();
                    wbk.Names["xunfallarbeitsmittel"].Value             = dt["Equipment"].ToString();
                    wbk.Names["xkoerperteil1"].Value                    = dt["ReportableBodypart"].ToString();
                    wbk.Names["xkoerperteil2"].Value                    = dt["ReportableBodypart2"].ToString();
                    wbk.Names["xkoerperteil3"].Value                    = dt["ReportableBodypart3"].ToString();
                    wbk.Names["xhauptverletzungsart"].Value             = dt["ReportableNOI"].ToString();
                    wbk.Names["xausfalldauer"].Value                    = dt["fLossClass"].ToString();
                    wbk.Names["chk_unfallanalyse"].Value                = dt["fHasAnalysis"].ToString();
                    wbk.Names["xhergang"].Value                         = dt["fCircumstances"].ToString();
                    wbk.Names["xdokumentennr"].Value                    = dt["fDocumentNumber"].ToString();
                    wbk.Names["xrevision"].Value                        = dt["fRevisionFooter"].ToString();
                    /* 3. render the report into the desired format */
                    package.SaveAs(chunk);
                    if (chunk.CanSeek)
                    {
                        chunk.Seek(0, SeekOrigin.Begin);
                    }
                    GeneratedFileType = FileType.ft_xls;
                    mime           = sherm.core.formatting.mime.GetMIMEFromFiletype(Outputformat);
                    TargetFilename = "2014 10 01 Sofortmeldung TKMI.xlsx";
                }
                /* succeeded */
                return(true);
            }
            catch (Exception ex)
            {
                /* some error */
                OnBuiltinReportError(ex.Message, ex);
                return(false);
            }
            finally
            {
                /* cleanup */
                try
                {
                    if (File.Exists(tmpfilename))
                    {
                        File.Delete(tmpfilename);
                    }
                }
                catch (Exception ef)
                {
                    Tracing.ErrorBkg("{0}", ef.ToString());
                }
            }
        }
示例#4
0
        protected override bool RenderInternal(ref MemoryStream chunk, out string mime)
        {
            mime = null;
            var  tmpfilename           = String.Format("{0}.xlsx", Guid.NewGuid().ToString());
            var  cutoff                = this.DateGenerated;
            bool with_detailed_history = PresentationOptions.HasFlag(ReportPresentationOptions.ShowSubrecords);
            bool suppress_zerolines    = PresentationOptions.HasFlag(ReportPresentationOptions.Suppresszero);

            try
            {
                /* 1. convert the flat data into a less entropic form */
                var emps = new Employees();
                var tops = new Topics();
                /* 1a. persons */
                DataTable tab_pers = Data.Tables[ReportDatatableIdentifiers.REPORT_DATATABLE_TRA001_OVERVIEW_PER];
                foreach (DataRow dr in tab_pers.Rows)
                {
                    var middlename  = dr["Middlename"].ToString();
                    var orgabbrev   = dr["OrgAbbrev"].ToString();
                    var orgshortcap = dr["OrgShortCap"].ToString(); /* (not used) */
                    var orglongcap  = dr["OrgLongCap"].ToString();
                    var orgcap      = orgabbrev;
                    if (orglongcap != orgabbrev)
                    {
                        orgcap = String.Format("{0} {1}", orgcap, orglongcap).TrimEnd();
                    }
                    var emp = new Employee()
                    {
                        PerID     = Convert.ToInt32(dr["PerID"]),
                        Lastname  = dr["Lastname"].ToString(),
                        Firstname = dr["Firstname"].ToString(),
                        PersNr    = dr["PersNr"].ToString(),
                        Company   = dr["Companyname"].ToString(),
                        OrgCap    = orgcap,
                    };
                    if (String.IsNullOrEmpty(middlename) == false)
                    {
                        emp.Lastname = String.Format("{0} {1}", middlename, emp.Lastname).TrimEnd(); /* van den Bosch */
                    }
                    emps.Add(emp.PerID, emp);
                }
                /* alleviate memory pressure */
                Data.Tables.Remove(tab_pers);
                tab_pers = null;
                /* 1b. all the rest (topics, participations) */
                DataTable tab_patn = Data.Tables[ReportDatatableIdentifiers.REPORT_DATATABLE_TRA001_OVERVIEW_PTN];
                foreach (DataRow dr in tab_patn.Rows)
                {
                    /* harvest */
                    var      PerID          = Convert.ToInt32(dr["PerID"]);
                    var      TopicID        = Convert.ToInt32(dr["TopicID"]);
                    var      Caption        = dr["Caption"].ToString();
                    DateTime DateTraining   = dr["DateTraining"].Equals(DBNull.Value) ? Convert.ToDateTime(dr["DateMeasure"]) : Convert.ToDateTime(dr["DateTraining"]);
                    DateTime?dateattended   = dr["DateAttended"].Equals(DBNull.Value) ? (DateTime?)null : Convert.ToDateTime(dr["DateAttended"]);
                    var      hasattended    = Convert.ToInt32(dr["HasAttended"]) > 0;
                    int?     validityfactor = null;
                    Timeunit?validityunit   = null;
                    if (dr["RequirementValidityFactor"].Equals(DBNull.Value) == false)
                    {
                        validityfactor = Convert.ToInt32(dr["RequirementValidityFactor"]);
                        validityunit   = (Timeunit)Convert.ToInt32(dr["RequirementValidityUnit"]);
                    }
                    /* logic rule: if attended, but no specific date given, value with assumption training date = attendance date */
                    if (hasattended && dateattended.HasValue == false)
                    {
                        dateattended = DateTraining;
                    }
                    /* logic rule: if a date attended is given, but the checkmark is not set, it may not count (C-1512-0454.1) */
                    if (hasattended == false && dateattended.HasValue)
                    {
                        dateattended = null;
                    }

                    /* slotify:
                     * 1c. the employee */
                    if (emps.ContainsKey(PerID))
                    {
                        var empX = emps[PerID];
                        if (empX.Attendances.Count(a => a.Key.Item1 == DateTraining && a.Key.Item2 == TopicID) == 0) /* [dlatikay 20170131] previously, this had only been checking for date, causing follow-up troubles mdettmarg @ C-1611-0558 */
                        {
                            var attendancestatus = StatisticalAttendanceStatus.WHITENotPlanned;
                            if (dateattended.HasValue)
                            {
                                attendancestatus = StatisticalAttendanceStatus.GREENAttended;
                            }
                            else
                            {
                                if (DateTraining >= cutoff)
                                {
                                    attendancestatus = StatisticalAttendanceStatus.WHITEPlanned;
                                }
                                else
                                {
                                    attendancestatus = StatisticalAttendanceStatus.REDOverdue;
                                }
                            }
                            var attx = new Attendance()
                            {
                                PerID         = PerID,
                                attended_when = dateattended,
                                DateTraining  = DateTraining,
                                TopicID       = TopicID,
                                Participation = attendancestatus
                            };
                            empX.Attendances.Add(new Tuple <DateTime, int>(DateTraining, TopicID), attx);

                            /* is this a (better) most recent attendance of this person?
                            * [dlatikay 20160402] likely the site of C-1512-0454.II.N */
                            if ((attx.attended_when ?? attx.DateTraining) <= cutoff && attx.Participation != StatisticalAttendanceStatus.WHITENotPlanned)
                            {
                                if (empX.MostRecentAttendance.ContainsKey(TopicID) == false)
                                {
                                    empX.MostRecentAttendance.Add(TopicID, attx);
                                }
                                else
                                {
                                    var cand = empX.MostRecentAttendance[TopicID];
                                    if ((cand.attended_when ?? cand.DateTraining) < (attx.attended_when ?? attx.DateTraining))
                                    {
                                        empX.MostRecentAttendance.Remove(TopicID);
                                        empX.MostRecentAttendance.Add(TopicID, attx);
                                    }
                                }
                            }
                        }
                    }
                    /* 1d. the topic */
                    if (tops.ContainsKey(TopicID) == false)
                    {
                        tops.Add(TopicID, new Topic()
                        {
                            TopicID        = TopicID,
                            Caption        = Caption,
                            ValidityFactor = validityfactor ?? ValidityFactorDefault,
                            ValidityUnit   = validityunit ?? ValidityUnitDefault
                        });
                    }
                    var top = tops[TopicID];
                    if (top.AttendanceSlots.Contains(DateTraining) == false)
                    {
                        top.AttendanceSlots.Add(DateTraining);
                    }
                }
                /* alleviate */
                Data.Tables.Remove(tab_patn);
                tab_patn = null;
                /* 2. instantiate the epplus templating engine */
                var template = new FileInfo(Path.Combine(CustomAbsPath, String.Format("{0}.xlsx", ResultFileBasename)));
                var dest     = new FileInfo(Path.Combine(RptTmpBasepath, tmpfilename));
                using (var package = new ExcelPackage(dest, template))
                {
                    ExcelWorkbook  wbk = package.Workbook;
                    ExcelWorksheet sht = wbk.Worksheets[1];
                    /* 2. populate the template into the new file */
                    //var dt = Data.Tables[ReportDatatableIdentifiers.REPORT_DATATABLE_HARDCOPY_SAFETY_003].Rows[0];
                    wbk.Names["Title"].Value       = m(5483);                       /* Excel® Training Overview */
                    wbk.Names["lCriteria"].Value   = m(4494, ReportQueryDateLocal); /* Data as per {0} */
                    wbk.Names["PersNr"].Value      = m(588);                        /* Employee # */
                    wbk.Names["Name"].Value        = m(744);                        /* Name */
                    wbk.Names["lFirstname"].Value  = m(478);                        /* First name */
                    wbk.Names["lDepartment"].Value = m(2279);                       /* Department */
                    wbk.Names["Company"].Value     = m(746);                        /* Company */
                    /* 2a. write the topics with their date slot headings horizontally */
                    var columnmap = new Dictionary <int, Dictionary <DateTime, int> >();
                    var col       = 6;
                    foreach (var top in from t in tops.Values orderby t.Caption, t.TopicID select t)
                    {
                        /* write topic header, 1 = most recent */
                        var spanning = 1 + top.AttendanceSlots.Count;
                        sht.Cells[4, col].Value = top.Caption;
                        sht.Cells[5, col].Value = "Letzte absolvierte Unterweisung";
                        columnmap.Add(top.TopicID, new Dictionary <DateTime, int>());
                        columnmap[top.TopicID].Add(DateTime.MinValue, col); /* this maps to the current topic's "most recent training" column */
                        ++col;
                        /* write topic date slots */
                        if (with_detailed_history)
                        {
                            bool first = true;
                            foreach (var dat in from d in top.AttendanceSlots orderby d select d)
                            {
                                if (dat >= DateFrom && dat <= DateTo)
                                {
                                    if (first)
                                    {
                                        sht.Cells[5, col].Value = "Plandatum";
                                        first = false;
                                    }
                                    sht.Cells[5, col].Value = dat;
                                    columnmap[top.TopicID].Add(dat, col); /* this maps to that "planned date" column of the current topic */
                                    sht.Cells[5, col].Style.Numberformat.Format = "dd.mm.yyyy";
                                    sht.Cells[5, col].Style.TextRotation        = 90;
                                    ++col;
                                }
                            }
                        }
                    }
                    /* 2b. write the employee names and static associated data vertically, omitting those with no data if we should */
                    int row = 7;
                    foreach (var emp in from e in emps.Values orderby e.Lastname, e.Firstname, e.PersNr, e.PerID select e)
                    {
                        if (suppress_zerolines == false || emp.Attendances.Count > 0)
                        {
                            sht.Cells[row, 1].Value = emp.PersNr;
                            sht.Cells[row, 2].Value = emp.Lastname;
                            sht.Cells[row, 3].Value = emp.Firstname;
                            sht.Cells[row, 4].Value = emp.OrgCap;
                            sht.Cells[row, 5].Value = emp.Company;

                            /* fill the topic/date slot-matrix body;
                             * write date of most recent training per topic */
                            foreach (var mra in from mrae in emp.MostRecentAttendance select mrae)
                            {
                                var topicid = mra.Key;
                                col = columnmap[topicid][DateTime.MinValue];
                                var status = emp.MostRecentAttendanceStatus(tops[topicid], cutoff);
                                if (status != StatisticalAttendanceStatusRecent.WHITENeverPlannedNorAttended)
                                {
                                    sht.Cells[row, col].Value = mra.Value.attended_when ?? mra.Value.DateTraining;
                                    sht.Cells[row, col].Style.Numberformat.Format = "dd.mm.yyyy";
                                    if (status == StatisticalAttendanceStatusRecent.GREENDoneAndValidToday)
                                    {
                                        sht.Cells[row, col].Style.Fill.PatternType = ExcelFillStyle.Solid;
                                        sht.Cells[row, col].Style.Fill.BackgroundColor.SetColor(Color.Green);
                                    }
                                    else if (status == StatisticalAttendanceStatusRecent.REDDoneButExpired)
                                    {
                                        sht.Cells[row, col].Style.Fill.PatternType = ExcelFillStyle.Solid;
                                        sht.Cells[row, col].Style.Fill.BackgroundColor.SetColor(Color.Red);
                                    }
                                }
                            }
                            /* if asked for, render the entire topic history of that empoyee */
                            if (with_detailed_history)
                            {
                                foreach (var att in from a in emp.Attendances.Values select a)
                                {
                                    if (att.DateTraining >= DateFrom && att.DateTraining <= DateTo)
                                    {
                                        col = columnmap[att.TopicID][att.DateTraining];
                                        if (att.Participation != StatisticalAttendanceStatus.WHITENotPlanned)
                                        {
                                            sht.Cells[row, col].Value = att.attended_when ?? att.DateTraining;
                                            sht.Cells[row, col].Style.Numberformat.Format = "dd.mm.yyyy";
                                            if (att.Participation == StatisticalAttendanceStatus.REDOverdue)
                                            {
                                                sht.Cells[row, col].Style.Fill.PatternType = ExcelFillStyle.Solid;
                                                sht.Cells[row, col].Style.Fill.BackgroundColor.SetColor(Color.Red);
                                            }
                                            else if (att.Participation == StatisticalAttendanceStatus.GREENAttended)
                                            {
                                                sht.Cells[row, col].Style.Fill.PatternType = ExcelFillStyle.Solid;
                                                sht.Cells[row, col].Style.Fill.BackgroundColor.SetColor(Color.Green);
                                            }
                                        }
                                    }
                                }
                            }
                            /* outer (pers/employee) advance */
                            ++row;
                        }
                    }
                    /* format properly */
                    sht.Cells.AutoFitColumns();
                    sht.View.FreezePanes(7, 1);
                    /* limit column 4=D in width */
                    sht.Column(4).Width = 38.29;
                    /* increase line 5 in height */
                    sht.Row(5).Height = 66.75;
                    /* 3. render the report into the desired format */
                    package.SaveAs(chunk);
                    if (chunk.CanSeek)
                    {
                        chunk.Seek(0, SeekOrigin.Begin);
                    }
                    GeneratedFileType = FileType.ft_xls;
                    mime           = sherm.core.formatting.mime.GetMIMEFromFiletype(Outputformat);
                    TargetFilename = String.Format("{0}{1}", ResultFileBasename, template.Extension);
                }
                /* succeeded */
                return(true);
            }
            catch (Exception ex)
            {
                /* some error */
                OnBuiltinReportError(ex.Message, ex);
                return(false);
            }
            finally
            {
                /* cleanup */
                try
                {
                    if (File.Exists(tmpfilename))
                    {
                        File.Delete(tmpfilename);
                    }
                }
                catch (Exception ef)
                {
                    Tracing.ErrorBkg("{0}", ef.ToString());
                }
            }
        }