public void Run(Stream stream, CMSDataContext db, IEnumerable <ContributorInfo> q, StatementSpecification cs, int set = 0) { pageEvents.set = set; pageEvents.PeopleId = 0; IEnumerable <ContributorInfo> contributors = q; var toDate = ToDate.Date.AddHours(24).AddSeconds(-1); PdfContentByte dc; var font = FontFactory.GetFont(FontFactory.HELVETICA, 11); var boldfont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11); var doc = new Document(PageSize.LETTER); doc.SetMargins(36f, 30f, 24f, 36f); var w = PdfWriter.GetInstance(doc, stream); w.PageEvent = pageEvents; doc.Open(); dc = w.DirectContent; var prevfid = 0; var runningtotals = db.ContributionsRuns.OrderByDescending(mm => mm.Id).First(); runningtotals.Processed = 0; db.SubmitChanges(); var count = 0; foreach (var ci in contributors) { if (set > 0 && pageEvents.FamilySet[ci.PeopleId] != set) { continue; } var contributions = APIContribution.Contributions(db, ci, FromDate, toDate, cs.Funds).ToList(); var pledges = APIContribution.Pledges(db, ci, toDate, cs.Funds).ToList(); var giftsinkind = APIContribution.GiftsInKind(db, ci, FromDate, toDate, cs.Funds).ToList(); var nontaxitems = db.Setting("DisplayNonTaxOnStatement", "false").ToBool() ? APIContribution.NonTaxItems(db, ci, FromDate, toDate, cs.Funds).ToList() : new List <NonTaxContribution>(); if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) == 0) { runningtotals.Processed += 1; runningtotals.CurrSet = set; db.SubmitChanges(); if (set == 0) { pageEvents.FamilySet[ci.PeopleId] = 0; } continue; } pageEvents.NextPeopleId = ci.PeopleId; doc.NewPage(); if (prevfid != ci.FamilyId) { prevfid = ci.FamilyId; pageEvents.EndPageSet(); pageEvents.PeopleId = ci.PeopleId; } if (set == 0) { pageEvents.FamilySet[ci.PeopleId] = 0; } count++; var css = @" <style> h1 { font-size: 24px; font-weight:normal; margin-bottom:0; } h2 { font-size: 11px; font-weight:normal; margin-top: 0; } p { font-size: 11px; } </style> "; //----Church Name var t1 = new PdfPTable(1); t1.TotalWidth = 72f * 5f; t1.DefaultCell.Border = Rectangle.NO_BORDER; string html1 = db.ContentHtml("StatementHeader", Resource1.ContributionStatementHeader); string html2 = db.ContentHtml("StatementNotice", Resource1.ContributionStatementNotice); var mh = new MyHandler(); using (var sr = new StringReader(css + html1)) XMLWorkerHelper.GetInstance().ParseXHtml(mh, sr); var cell = new PdfPCell(t1.DefaultCell); foreach (var e in mh.elements) { if (e.Chunks.Count > 0) { cell.AddElement(e); } } //cell.FixedHeight = 72f * 1.25f; t1.AddCell(cell); t1.AddCell("\n"); var t1a = new PdfPTable(1); t1a.TotalWidth = 72f * 5f; t1a.DefaultCell.Border = Rectangle.NO_BORDER; var ae = new PdfPTable(1); ae.DefaultCell.Border = Rectangle.NO_BORDER; ae.WidthPercentage = 100; var a = new PdfPTable(1); a.DefaultCell.Indent = 25f; a.DefaultCell.Border = Rectangle.NO_BORDER; a.AddCell(new Phrase(ci.Name, font)); foreach (var line in ci.MailingAddress.SplitLines()) { a.AddCell(new Phrase(line, font)); } cell = new PdfPCell(a) { Border = Rectangle.NO_BORDER }; //cell.FixedHeight = 72f * 1.0625f; ae.AddCell(cell); cell = new PdfPCell(t1a.DefaultCell); cell.AddElement(ae); t1a.AddCell(ae); //-----Notice var t2 = new PdfPTable(1); t2.TotalWidth = 72f * 3f; t2.DefaultCell.Border = Rectangle.NO_BORDER; var envno = ""; if (db.Setting("PrintEnvelopeNumberOnStatement")) { var ev = Person.GetExtraValue(db, ci.PeopleId, "EnvelopeNumber"); var s = Util.PickFirst(ev.Data, ev.IntValue.ToString(), ev.StrValue); if (s.HasValue()) { envno = $" env: {Util.PickFirst(ev.Data, ev.IntValue.ToString(), ev.StrValue)}"; } } t2.AddCell(db.Setting("NoPrintDateOnStatement") ? new Phrase($"\nid:{ci.PeopleId}{envno} {ci.CampusId}", font) : new Phrase($"\nprinted: {DateTime.Now:M/d/yy} id:{ci.PeopleId}{envno} {ci.CampusId}", font)); t2.AddCell(""); var mh2 = new MyHandler(); using (var sr = new StringReader(css + html2)) XMLWorkerHelper.GetInstance().ParseXHtml(mh2, sr); cell = new PdfPCell(t1.DefaultCell); foreach (var e in mh2.elements) { if (e.Chunks.Count > 0) { cell.AddElement(e); } } t2.AddCell(cell); // POSITIONING OF ADDRESSES //----Header var yp = doc.BottomMargin + db.Setting("StatementRetAddrPos", "10.125").ToFloat() * 72f; t1.WriteSelectedRows(0, -1, doc.LeftMargin - 0.1875f * 72f, yp, dc); yp = doc.BottomMargin + db.Setting("StatementAddrPos", "8.3375").ToFloat() * 72f; t1a.WriteSelectedRows(0, -1, doc.LeftMargin, yp, dc); yp = doc.BottomMargin + 10.125f * 72f; t2.WriteSelectedRows(0, -1, doc.LeftMargin + 72f * 4.4f, yp, dc); //----Contributions doc.Add(new Paragraph(" ")); doc.Add(new Paragraph(" ") { SpacingBefore = 72f * 2.125f }); doc.Add(new Phrase($"\n Period: {FromDate:d} - {toDate:d}", boldfont)); var pos = w.GetVerticalPosition(true); var ct = new ColumnText(dc); float gutter = 20f; float colwidth = (doc.Right - doc.Left - gutter) / 2; var t = new PdfPTable(new[] { 10f, 24f, 10f }); t.WidthPercentage = 100; t.DefaultCell.Border = Rectangle.NO_BORDER; t.HeaderRows = 2; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 3; cell.Phrase = new Phrase("Contributions\n", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.BOTTOM_BORDER; t.AddCell(new Phrase("Date", boldfont)); t.AddCell(new Phrase("Description", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase("Amount", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.NO_BORDER; var total = 0m; foreach (var c in contributions) { t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font)); t.AddCell(new Phrase(c.FundName, font)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font); t.AddCell(cell); total += (c.ContributionAmount ?? 0); } t.DefaultCell.Border = Rectangle.TOP_BORDER; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 2; cell.Phrase = new Phrase("Total Contributions for period", boldfont); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(total.ToString("N2"), font); t.AddCell(cell); ct.AddElement(t); //------Pledges if (pledges.Count > 0) { t = new PdfPTable(new float[] { 16f, 12f, 12f }); t.WidthPercentage = 100; t.DefaultCell.Border = Rectangle.NO_BORDER; t.HeaderRows = 2; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 3; cell.Phrase = new Phrase("\n\nPledges\n", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.BOTTOM_BORDER; t.AddCell(new Phrase("Fund", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase("Pledge", boldfont); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase("Given", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.NO_BORDER; foreach (var c in pledges) { t.AddCell(new Phrase(c.FundName, font)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(c.Pledged.ToString2("N2"), font); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(c.Given.ToString2("N2"), font); t.AddCell(cell); } ct.AddElement(t); } //------Gifts In Kind if (giftsinkind.Count > 0) { t = new PdfPTable(new float[] { 12f, 18f, 20f }); t.WidthPercentage = 100; t.DefaultCell.Border = Rectangle.NO_BORDER; t.HeaderRows = 2; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 3; cell.Phrase = new Phrase("\n\nGifts in Kind\n", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.BOTTOM_BORDER; t.AddCell(new Phrase("Date", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.Phrase = new Phrase("Fund", boldfont); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.Phrase = new Phrase("Description", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.NO_BORDER; foreach (var c in giftsinkind) { t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font)); cell = new PdfPCell(t.DefaultCell); cell.Phrase = new Phrase(c.FundName, font); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.Phrase = new Phrase(c.Description, font); t.AddCell(cell); } ct.AddElement(t); } //-----Summary t = new PdfPTable(new float[] { 29f, 9f }); t.WidthPercentage = 100; t.DefaultCell.Border = Rectangle.NO_BORDER; t.HeaderRows = 2; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 2; cell.Phrase = new Phrase("\n\nPeriod Summary\n", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.BOTTOM_BORDER; t.AddCell(new Phrase("Fund", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase("Amount", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.NO_BORDER; foreach (var c in APIContribution.GiftSummary(db, ci, FromDate, toDate, cs.Funds)) { t.AddCell(new Phrase(c.FundName, font)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(c.Total.ToString2("N2"), font); t.AddCell(cell); } t.DefaultCell.Border = Rectangle.TOP_BORDER; t.AddCell(new Phrase("Total contributions for period", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(total.ToString("N2"), font); t.AddCell(cell); ct.AddElement(t); //------NonTax if (nontaxitems.Count > 0) { t = new PdfPTable(new float[] { 10f, 24f, 10f }); t.WidthPercentage = 100; t.DefaultCell.Border = Rectangle.NO_BORDER; t.HeaderRows = 2; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 3; cell.Phrase = new Phrase("\n\nNon Tax-Deductible Items\n", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.BOTTOM_BORDER; t.AddCell(new Phrase("Date", boldfont)); t.AddCell(new Phrase("Description", boldfont)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase("Amount", boldfont); t.AddCell(cell); t.DefaultCell.Border = Rectangle.NO_BORDER; var ntotal = 0m; foreach (var c in nontaxitems) { t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font)); t.AddCell(new Phrase(c.FundName, font)); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font); t.AddCell(cell); ntotal += (c.ContributionAmount ?? 0); } t.DefaultCell.Border = Rectangle.TOP_BORDER; cell = new PdfPCell(t.DefaultCell); cell.Colspan = 2; cell.Phrase = new Phrase("Total Non Tax-Deductible Items for period", boldfont); t.AddCell(cell); cell = new PdfPCell(t.DefaultCell); cell.HorizontalAlignment = Element.ALIGN_RIGHT; cell.Phrase = new Phrase(ntotal.ToString("N2"), font); t.AddCell(cell); ct.AddElement(t); } var col = 0; var status = 0; while (ColumnText.HasMoreText(status)) { if (col == 0) { ct.SetSimpleColumn(doc.Left, doc.Bottom, doc.Left + colwidth, pos); } else if (col == 1) { ct.SetSimpleColumn(doc.Right - colwidth, doc.Bottom, doc.Right, pos); } status = ct.Go(); ++col; if (col > 1) { col = 0; pos = doc.Top; doc.NewPage(); } } runningtotals.Processed += 1; runningtotals.CurrSet = set; db.SubmitChanges(); } if (count == 0) { doc.NewPage(); doc.Add(new Paragraph("no data")); var a = new Anchor("see this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html") { Reference = "http://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting" }; doc.Add(a); } doc.Close(); if (set == LastSet()) { runningtotals.Completed = DateTime.Now; } db.SubmitChanges(); }
private void HtmlToPdfMethod(Stream stream, CMSDataContext db, IEnumerable <ContributorInfo> q, StatementSpecification cs, int set) { IConverter converter = GetConverter(); string nameOfChurch = db.Setting("NameOfChurch", "Name of Church"); string startAddress = db.Setting("StartAddress", "Start Address"); string churchPhone = db.Setting("ChurchPhone", "(000) 000-0000"); string html = cs.Template ?? db.Content("StatementTemplate", Resource1.ContributionStatementTemplate, ContentTypeCode.TypeText).Body; string bodyHtml = cs.TemplateBody ?? db.Content("StatementTemplateBody", Resource1.ContributionStatementTemplateBody, ContentTypeCode.TypeText).Body; string header = cs.Header ?? db.Content("StatementHeader", string.Format(Resource1.ContributionStatementHeader, nameOfChurch, startAddress, churchPhone), ContentTypeCode.TypeHtml).Body; string notice = cs.Notice ?? db.Content("StatementNotice", string.Format(Resource1.ContributionStatementNotice, nameOfChurch), ContentTypeCode.TypeHtml).Body; string footer = cs.Footer ?? db.Content("StatementTemplateFooter", "", ContentTypeCode.TypeText).Body; ContributionsRun runningtotals = db.ContributionsRuns.Where(mm => mm.UUId == UUId).SingleOrDefault(); StatementOptions options; if (!GetStatementOptions(bodyHtml, out options)) { GetStatementOptions(html, out options); } var toDate = ToDate.Date.AddHours(24).AddSeconds(-1); var document = new HtmlToPdfDocument { GlobalSettings = { DocumentTitle = (cs.Description ?? "Contribution Statement {date}").Replace("{date}", $"{toDate:d}"), Margins = options.Margins.Settings, PaperSize = options.PaperSize, ProduceOutline = false, } }; var familiesInSet = pageEvents.FamilySet.Where(k => k.Value == set).Select(k => k.Key); var contributors = q.Where(c => set == 0 || familiesInSet.Contains(c.FamilyId)); var count = contributors.Count(); if (count == 0) { document.Objects.Add(new ObjectSettings { HtmlText = @"<p>no data</p> <a href=""https://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting""> See this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html </a>" }); var bytes = converter.Convert(document); stream.Write(bytes, 0, bytes.Length); return; } if (runningtotals != null) { runningtotals.Processed = 0; } db.SubmitChanges(); Document combinedPDF = new Document(); var combinedPDFName = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.pdf"); using (FileStream combinedStream = new FileStream(combinedPDFName, FileMode.Create)) { using (PdfCopy writer = new PdfCopy(combinedPDF, combinedStream)) { combinedPDF.Open(); var lastFamilyId = 0; foreach (var contributor in contributors) { if (runningtotals != null) { runningtotals.Processed += 1; runningtotals.CurrSet = set; db.SubmitChanges(); } if (lastFamilyId != contributor.FamilyId) { lastFamilyId = contributor.FamilyId; if (set == 0) { pageEvents.FamilySet[contributor.FamilyId] = 0; } } var contributions = APIContribution.Contributions(db, contributor, FromDate, toDate, cs.Funds).ToList(); var pledges = APIContribution.Pledges(db, contributor, toDate, cs.Funds).ToList(); var giftsinkind = APIContribution.GiftsInKind(db, contributor, FromDate, toDate, cs.Funds).ToList(); var nontaxitems = APIContribution.NonTaxItems(db, contributor, FromDate, toDate, cs.Funds).ToList(); if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) > 0) { contributor.MailingAddress = string.Join("<br/>", contributor.MailingAddress.SplitLines()); var taxSummary = SumByFund(contributions); var nontaxSummary = SumByFund(nontaxitems.Select(i => new NormalContribution(i)).ToList()); if (options.CombinedTaxSummary) { taxSummary.Combine(SumByFund(giftsinkind.Select(i => new NormalContribution(i)).ToList())); } var data = new StatementContext { fromDate = FromDate, toDate = toDate, header = "", notice = "", now = DateTime.Now, body = "", footer = "", contributor = contributor, envelopeNumber = Convert.ToString(Person.GetExtraValue(db, contributor.PeopleId, "EnvelopeNumber")?.IntValue), contributions = new ListOfNormalContributions(contributions), pledges = pledges, giftsinkind = giftsinkind, nontaxitems = nontaxitems, taxSummary = taxSummary, nontaxSummary = nontaxSummary, totalGiven = taxSummary.Total + nontaxSummary.Total }; data.header = db.RenderTemplate(header, data); data.notice = db.RenderTemplate(notice, data); data.body = db.RenderTemplate(bodyHtml, data); data.footer = db.RenderTemplate(footer, data); var htmlDocument = db.RenderTemplate(html, data); document.Objects.Clear(); document.Objects.Add(new ObjectSettings { CountPages = true, FooterSettings = options.Footer.Settings, HeaderSettings = options.Header.Settings, HtmlText = htmlDocument, WebSettings = new WebSettings { EnableJavascript = false, PrintBackground = true }, LoadSettings = new LoadSettings { BlockLocalFileAccess = true } }); } else { continue; } var bytes = converter.Convert(document); var pageCount = 0; using (PdfReader reader = new PdfReader(bytes)) { pageCount = reader.NumberOfPages; for (int p = 0; p < pageCount; p++) { var page = writer.GetImportedPage(reader, p + 1); writer.AddPage(page); } } if (set == 0) { pageEvents.FamilySet[contributor.FamilyId] += pageCount; } } } } using (var combined = File.OpenRead(combinedPDFName)) { combined.CopyTo(stream); } }