wxString mmReportCategoryExpenses::getHTMLText() { RefreshData(); valueList_.clear(); // Data is presorted by name std::vector<data_holder> sortedData(data_); std::map <int, int> group_counter; std::map <int, double> group_total; for (const auto& entry : sortedData) { group_counter[entry.categs]++; group_total[entry.categs] += entry.amount; group_total[-1] += entry.amount < 0 ? entry.amount : 0; group_total[-2] += entry.amount > 0 ? entry.amount : 0; if (type_ != NONE) valueList_.push_back({ entry.color, entry.name, entry.amount }); } std::stable_sort(valueList_.begin(), valueList_.end() , [](const ValueTrio& x, const ValueTrio& y) { if (x.amount != y.amount) return fabs(x.amount) > fabs(y.amount); else return x.label < y.label; } ); mmHTMLBuilder hb; hb.init(); hb.addDivContainer(); hb.addHeader(2, title_); hb.DisplayDateHeading(date_range_->start_date(), date_range_->end_date(), with_date_); hb.addDivRow(); hb.addDivCol17_67(); // Add the graph hb.addDivCol25_50(); if (type_ != NONE && !valueList_.empty()) hb.addPieChart(valueList_, "Categories"); hb.endDiv(); hb.startTable(); hb.startThead(); hb.startTableRow(); if (type_ != NONE) hb.addTableHeaderCell(" "); hb.addTableHeaderCell(_("Category")); hb.addTableHeaderCell(_("Amount"), true); hb.addTableHeaderCell(_("Total"), true); hb.endTableRow(); hb.endThead(); hb.startTbody(); int group = 0; for (const auto& entry : sortedData) { group++; hb.startTableRow(); if (type_ != NONE) hb.addColorMarker(entry.color); hb.addTableCell(entry.name); hb.addMoneyCell(entry.amount); if (group_counter[entry.categs] > 1) hb.addTableCell(""); else hb.addMoneyCell(entry.amount); hb.endTableRow(); if (group_counter[entry.categs] == group && group_counter[entry.categs] > 1) { group = 0; hb.startTableRow(); if (type_ != NONE) hb.addTableCell(""); hb.addTableCell(_("Category Total: ")); hb.addTableCell(""); hb.addMoneyCell(group_total[entry.categs]); hb.endTableRow(); } if (group_counter[entry.categs] == 1 || group == 0) { group = 0; } } hb.endTbody(); int span = (type_ != NONE) ? 4 : 3; hb.startTfoot(); if (type_ == NONE) { hb.addTotalRow(_("Total Expenses:"), span, group_total[-1]); hb.addTotalRow(_("Total Income:"), span, group_total[-2]); } hb.addTotalRow(_("Grand Total:"), span, group_total[-1] + group_total[-2]); hb.endTfoot(); hb.endTable(); hb.endDiv(); hb.endDiv(); hb.endDiv(); hb.end(); Model_Report::outputReportFile(hb.getHTMLText()); return ""; }
wxString mmReportCategoryExpenses::getHTMLText() { RefreshData(); // Data is presorted by name std::vector<data_holder> sortedData(data_); std::vector<ValueTrio> expensesList, incomeList; std::map <int, int> group_counter; std::map <int, double> group_total; for (const auto& entry : sortedData) { group_counter[entry.categs]++; group_total[entry.categs] += entry.amount; group_total[-1] += entry.amount < 0 ? entry.amount : 0; group_total[-2] += entry.amount > 0 ? entry.amount : 0; if (getChartSelection() == 0) { if (entry.amount < 0) expensesList.push_back({ entry.color, entry.name, entry.amount }); else if (entry.amount > 0) incomeList.push_back({ entry.color, entry.name, entry.amount }); } } std::stable_sort(expensesList.begin(), expensesList.end(), DataSorter); std::stable_sort(incomeList.begin(), incomeList.end(), DataSorter); mmHTMLBuilder hb; hb.init(); hb.addDivContainer(); hb.addHeader(2, title()); hb.addDateNow(); hb.DisplayDateHeading(m_date_range->start_date(), m_date_range->end_date(), m_date_range->is_with_date()); hb.addDivRow(); hb.addDivCol17_67(); // Add the graph if (getChartSelection() == 0) { if (type_ == CATEGORY) { hb.addDivCol17_67(); hb.addText("<table><tr><th style='text-align: center'>"); hb.addText(_("Expenses")); hb.addText("</th><th /><th style='text-align: center'>"); hb.addText(_("Income")); hb.addText("</th></tr><tr><td>"); if (!expensesList.empty()) hb.addPieChart(expensesList, "Expenses"); hb.addText("</td><td /><td>"); if (!incomeList.empty()) hb.addPieChart(incomeList, "Income"); hb.addText("</td></tr></table>"); hb.endDiv(); } else { hb.addDivCol25_50(); if (!expensesList.empty()) hb.addPieChart(expensesList, "Expenses"); if (!incomeList.empty()) hb.addPieChart(incomeList, "Income"); hb.endDiv(); } } hb.startTable(); hb.startThead(); hb.startTableRow(); if (getChartSelection() == 0) hb.addTableHeaderCell(" "); hb.addTableHeaderCell(_("Category")); hb.addTableHeaderCell(_("Amount"), true); hb.addTableHeaderCell(_("Total"), true); hb.endTableRow(); hb.endThead(); hb.startTbody(); int group = 0; for (const auto& entry : sortedData) { group++; hb.startTableRow(); if (getChartSelection() == 0) hb.addColorMarker(entry.color); hb.addTableCell(entry.name); hb.addMoneyCell(entry.amount); if (group_counter[entry.categs] > 1) hb.addTableCell(""); else hb.addMoneyCell(entry.amount); hb.endTableRow(); if (group_counter[entry.categs] == group && group_counter[entry.categs] > 1) { group = 0; hb.startTableRow(); if (getChartSelection() == 0) hb.addTableCell(""); hb.addTableCell(_("Category Total: ")); hb.addTableCell(""); hb.addMoneyCell(group_total[entry.categs]); hb.endTableRow(); } if (group_counter[entry.categs] == 1 || group == 0) { group = 0; } } hb.endTbody(); int span = (getChartSelection() == 0) ? 4 : 3; hb.startTfoot(); if (type_ == CATEGORY) { hb.addTotalRow(_("Total Expenses:"), span, group_total[-1]); hb.addTotalRow(_("Total Income:"), span, group_total[-2]); } hb.addTotalRow(_("Grand Total:"), span, group_total[-1] + group_total[-2]); hb.endTfoot(); hb.endTable(); hb.endDiv(); hb.endDiv(); hb.endDiv(); hb.end(); return hb.getHTMLText(); }
wxString mmReportCategoryExpenses::getHTMLText() { // Data is presorted by name std::vector<data_holder> sortedData(data_); if (CATEGORY_SORT_BY_AMOUNT == sortColumn_) { std::stable_sort(sortedData.begin(), sortedData.end() , [] (const data_holder& x, const data_holder& y) { if (x.amount != y.amount) return x.amount < y.amount; else return x.name < y.name; } ); } std::map <int, int> group_counter; std::map <int, double> group_total; for (const auto& entry : sortedData) { group_counter[entry.categs]++; group_total[entry.categs] += entry.amount; group_total[-1] += entry.amount < 0 ? entry.amount : 0; group_total[-2] += entry.amount > 0 ? entry.amount : 0; } mmHTMLBuilder hb; hb.init(); hb.addHeader(2, title_); hb.DisplayDateHeading(date_range_->start_date(), date_range_->end_date(), with_date_); hb.startCenter(); // Add the graph hb.startTable("100%"); hb.startTableRow(); hb.startTableCell("50%"); mmGraphPie ggtotal; hb.addImage(ggtotal.getOutputFileName()); ggtotal.init(valueListTotals_); ggtotal.Generate(_("Categories")); hb.endTableCell(); hb.startTableCell("50%"); mmGraphPie gg; hb.addImage(gg.getOutputFileName()); gg.init(valueList_); gg.Generate(_("Subcategories")); hb.endTableCell(); hb.endTableRow(); hb.endTable(); hb.startTable("60%"); hb.startTableRow(); if(CATEGORY_SORT_BY_NAME == sortColumn_) hb.addTableHeaderCell(_("Category")); else hb.addTableHeaderCellLink(wxString::Format("sort:%d", CATEGORY_SORT_BY_NAME), _("Category")); if(CATEGORY_SORT_BY_AMOUNT == sortColumn_) hb.addTableHeaderCell(_("Amount"), true); else hb.addTableHeaderCellLink(wxString::Format("sort:%d", CATEGORY_SORT_BY_AMOUNT), _("Amount"), true); hb.addTableHeaderCell(_("Total"), true); hb.endTableRow(); int group = 0; for (const auto& entry : sortedData) { group++; hb.startTableRow(); hb.addTableCell(entry.name, false, true); hb.addMoneyCell(entry.amount); if (group_counter[entry.categs] > 1) hb.addTableCell(""); else hb.addMoneyCell(entry.amount); hb.endTableRow(); if (group_counter[entry.categs] == group && group_counter[entry.categs] > 1) { group = 0; hb.startTableRow(); hb.addTableCell(_("Category Total: "), false, true, true, "GRAY"); hb.addTableCell(""); hb.addMoneyCell(group_total[entry.categs], "GRAY"); hb.endTableRow(); } if (group_counter[entry.categs] == 1 || group == 0) { hb.addRowSeparator(3); group = 0; } } if (type_ == NONE) { hb.addTotalRow(_("Total Expenses: "), 3, group_total[-1]); hb.addTotalRow(_("Total Income: "), 3, group_total[-2]); } hb.addTotalRow(_("Grand Total: "), 3, group_total[-1] + group_total[-2]); hb.endTable(); hb.endCenter(); hb.end(); return hb.getHTMLText(); }