use of jgnash.engine.AccountGroup in project jgnash by ccavanaugh.
the class BudgetResultsExport method exportBudgetResultsModel.
/**
* Exports a {@code BudgetResultsModel} to a spreadsheet.
*
* @param file File to save to
* @param model Results model to export
* @return Error message
*/
public static String exportBudgetResultsModel(final Path file, final BudgetResultsModel model) {
String message = null;
final ResourceBundle rb = ResourceUtils.getBundle();
final String extension = FileUtils.getFileExtension(file.toString());
try (final Workbook wb = extension.equals("xlsx") ? new XSSFWorkbook() : new HSSFWorkbook()) {
final CreationHelper createHelper = wb.getCreationHelper();
// create a new sheet
final Sheet s = wb.createSheet(model.getBudget().getName());
// create header cell styles
final CellStyle headerStyle = wb.createCellStyle();
// create 2 fonts objects
final Font amountFont = wb.createFont();
final Font headerFont = wb.createFont();
amountFont.setFontHeightInPoints((short) 10);
amountFont.setColor(IndexedColors.BLACK.getIndex());
headerFont.setFontHeightInPoints((short) 11);
headerFont.setColor(IndexedColors.BLACK.getIndex());
headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
// Set the other cell style and formatting
headerStyle.setBorderBottom(CellStyle.BORDER_THIN);
headerStyle.setBorderTop(CellStyle.BORDER_THIN);
headerStyle.setBorderLeft(CellStyle.BORDER_THIN);
headerStyle.setBorderRight(CellStyle.BORDER_THIN);
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
headerStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
DataFormat df_header = wb.createDataFormat();
headerStyle.setDataFormat(df_header.getFormat("text"));
headerStyle.setFont(headerFont);
headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
int row = 0;
Row r = s.createRow(row);
// create period headers
for (int i = 0; i < model.getDescriptorList().size(); i++) {
Cell c = r.createCell(i * 3 + 1);
c.setCellValue(createHelper.createRichTextString(model.getDescriptorList().get(i).getPeriodDescription()));
c.setCellStyle(headerStyle);
s.addMergedRegion(new CellRangeAddress(row, row, i * 3 + 1, i * 3 + 3));
}
{
int col = model.getDescriptorList().size() * 3 + 1;
Cell c = r.createCell(col);
c.setCellValue(createHelper.createRichTextString(rb.getString("Title.Summary")));
c.setCellStyle(headerStyle);
s.addMergedRegion(new CellRangeAddress(row, row, col, col + 2));
}
// create results header columns
row++;
r = s.createRow(row);
{
Cell c = r.createCell(0);
c.setCellValue(createHelper.createRichTextString(rb.getString("Column.Account")));
c.setCellStyle(headerStyle);
for (int i = 0; i <= model.getDescriptorList().size(); i++) {
c = r.createCell(i * 3 + 1);
c.setCellValue(createHelper.createRichTextString(rb.getString("Column.Budgeted")));
c.setCellStyle(headerStyle);
c = r.createCell(i * 3 + 2);
c.setCellValue(createHelper.createRichTextString(rb.getString("Column.Actual")));
c.setCellStyle(headerStyle);
c = r.createCell(i * 3 + 3);
c.setCellValue(createHelper.createRichTextString(rb.getString("Column.Remaining")));
c.setCellStyle(headerStyle);
}
}
// must sort the accounts, otherwise child structure is not correct
List<Account> accounts = new ArrayList<>(model.getAccounts());
accounts.sort(Comparators.getAccountByTreePosition(Comparators.getAccountByCode()));
// create account rows
for (final Account account : accounts) {
final DataFormat df = wb.createDataFormat();
final DecimalFormat format = (DecimalFormat) CommodityFormat.getFullNumberFormat(account.getCurrencyNode());
final String pattern = format.toLocalizedPattern().replace("¤", account.getCurrencyNode().getPrefix());
final CellStyle amountStyle = wb.createCellStyle();
amountStyle.setFont(amountFont);
amountStyle.setDataFormat(df.getFormat(pattern));
// Sets cell indentation, only impacts display if users changes the cell formatting to be left aligned.
amountStyle.setIndention((short) (model.getDepth(account) * 2));
row++;
int col = 0;
r = s.createRow(row);
CellStyle cs = wb.createCellStyle();
cs.cloneStyleFrom(headerStyle);
cs.setAlignment(CellStyle.ALIGN_LEFT);
cs.setIndention((short) (model.getDepth(account) * 2));
Cell c = r.createCell(col);
c.setCellValue(createHelper.createRichTextString(account.getName()));
c.setCellStyle(cs);
List<CellReference> budgetedRefList = new ArrayList<>();
List<CellReference> changeRefList = new ArrayList<>();
List<CellReference> remainingRefList = new ArrayList<>();
for (int i = 0; i < model.getDescriptorList().size(); i++) {
BudgetPeriodResults results = model.getResults(model.getDescriptorList().get(i), account);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_NUMERIC);
c.setCellValue(results.getBudgeted().doubleValue());
c.setCellStyle(amountStyle);
CellReference budgetedRef = new CellReference(row, col);
budgetedRefList.add(budgetedRef);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_NUMERIC);
c.setCellValue(results.getChange().doubleValue());
c.setCellStyle(amountStyle);
CellReference changeRef = new CellReference(row, col);
changeRefList.add(changeRef);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_FORMULA);
c.setCellStyle(amountStyle);
c.setCellFormula(budgetedRef.formatAsString() + "-" + changeRef.formatAsString());
CellReference remainingRef = new CellReference(row, col);
remainingRefList.add(remainingRef);
}
// add summary columns
addSummaryCell(r, ++col, budgetedRefList, amountStyle);
addSummaryCell(r, ++col, changeRefList, amountStyle);
addSummaryCell(r, ++col, remainingRefList, amountStyle);
}
// add group summary rows
for (final AccountGroup group : model.getAccountGroupList()) {
final DataFormat df = wb.createDataFormat();
final CellStyle amountStyle = wb.createCellStyle();
amountStyle.setFont(amountFont);
amountStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
amountStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
amountStyle.setBorderBottom(CellStyle.BORDER_THIN);
amountStyle.setBorderTop(CellStyle.BORDER_THIN);
amountStyle.setBorderLeft(CellStyle.BORDER_THIN);
amountStyle.setBorderRight(CellStyle.BORDER_THIN);
final DecimalFormat format = (DecimalFormat) CommodityFormat.getFullNumberFormat(model.getBaseCurrency());
final String pattern = format.toLocalizedPattern().replace("¤", model.getBaseCurrency().getPrefix());
amountStyle.setDataFormat(df.getFormat(pattern));
row++;
int col = 0;
r = s.createRow(row);
CellStyle cs = wb.createCellStyle();
cs.cloneStyleFrom(headerStyle);
cs.setAlignment(CellStyle.ALIGN_LEFT);
Cell c = r.createCell(col);
c.setCellValue(createHelper.createRichTextString(group.toString()));
c.setCellStyle(cs);
List<CellReference> budgetedRefList = new ArrayList<>();
List<CellReference> changeRefList = new ArrayList<>();
List<CellReference> remainingRefList = new ArrayList<>();
for (int i = 0; i < model.getDescriptorList().size(); i++) {
BudgetPeriodResults results = model.getResults(model.getDescriptorList().get(i), group);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_NUMERIC);
c.setCellValue(results.getBudgeted().doubleValue());
c.setCellStyle(amountStyle);
CellReference budgetedRef = new CellReference(row, col);
budgetedRefList.add(budgetedRef);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_NUMERIC);
c.setCellValue(results.getChange().doubleValue());
c.setCellStyle(amountStyle);
CellReference changeRef = new CellReference(row, col);
changeRefList.add(changeRef);
c = r.createCell(++col);
c.setCellType(Cell.CELL_TYPE_FORMULA);
c.setCellStyle(amountStyle);
c.setCellFormula(budgetedRef.formatAsString() + "-" + changeRef.formatAsString());
CellReference remainingRef = new CellReference(row, col);
remainingRefList.add(remainingRef);
}
// add summary columns
addSummaryCell(r, ++col, budgetedRefList, amountStyle);
addSummaryCell(r, ++col, changeRefList, amountStyle);
addSummaryCell(r, ++col, remainingRefList, amountStyle);
}
// force evaluation
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateAll();
short columnCount = s.getRow(1).getLastCellNum();
// autosize all of the columns + 10 pixels
for (int i = 0; i <= columnCount; i++) {
s.autoSizeColumn(i);
s.setColumnWidth(i, s.getColumnWidth(i) + 10);
}
Logger.getLogger(BudgetResultsExport.class.getName()).log(Level.INFO, "{0} cell styles were used", wb.getNumCellStyles());
// Save
String filename = file.toString();
if (wb instanceof XSSFWorkbook) {
filename = FileUtils.stripFileExtension(filename) + ".xlsx";
} else {
filename = FileUtils.stripFileExtension(filename) + ".xls";
}
try (final OutputStream out = Files.newOutputStream(Paths.get(filename))) {
wb.write(out);
} catch (final Exception e) {
Logger.getLogger(BudgetResultsExport.class.getName()).log(Level.SEVERE, e.getLocalizedMessage(), e);
message = e.getLocalizedMessage();
}
} catch (IOException e) {
Logger.getLogger(BudgetResultsExport.class.getName()).log(Level.SEVERE, e.getLocalizedMessage(), e);
}
return message;
}
use of jgnash.engine.AccountGroup in project jgnash by ccavanaugh.
the class BudgetTableController method buildAccountTypeTable.
private void buildAccountTypeTable() {
final TableColumn<AccountGroup, String> nameColumn = new TableColumn<>(resources.getString("Column.Type"));
nameColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().toString()));
accountTypeTable.getColumns().add(nameColumn);
}
use of jgnash.engine.AccountGroup in project jgnash by ccavanaugh.
the class BudgetTableController method updateSparkLines.
private void updateSparkLines() {
sparkLinePane.getChildren().clear();
for (final AccountGroup group : accountGroupList) {
List<BigDecimal> remaining = budgetResultsModel.getDescriptorList().parallelStream().map(descriptor -> budgetResultsModel.getResults(descriptor, group).getRemaining()).collect(Collectors.toList());
final HBox hBox = new HBox(new Label(group.toString()), new BudgetSparkLine(remaining));
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getStylesheets().addAll(MainView.DEFAULT_CSS);
sparkLinePane.getChildren().add(hBox);
}
}
use of jgnash.engine.AccountGroup in project jgnash by ccavanaugh.
the class BudgetTableController method buildAccountPeriodSummaryColumn.
private TableColumn<AccountGroup, BigDecimal> buildAccountPeriodSummaryColumn(final int index) {
final BudgetPeriodDescriptor descriptor = budgetResultsModel.getDescriptorList().get(index);
final TableColumn<AccountGroup, BigDecimal> headerColumn = new TableColumn<>(descriptor.getPeriodDescription());
final TableColumn<AccountGroup, BigDecimal> budgetedColumn = new TableColumn<>(resources.getString("Column.Budgeted"));
budgetedColumn.setCellValueFactory(param -> {
if (param.getValue() != null) {
return new SimpleObjectProperty<>(budgetResultsModel.getResults(descriptor, param.getValue()).getBudgeted());
}
return new SimpleObjectProperty<>(BigDecimal.ZERO);
});
budgetedColumn.setCellFactory(param -> new AccountGroupTableCell());
budgetedColumn.minWidthProperty().bind(columnWidth);
budgetedColumn.maxWidthProperty().bind(columnWidth);
budgetedColumn.setSortable(false);
budgetedColumn.resizableProperty().set(false);
headerColumn.getColumns().add(budgetedColumn);
final TableColumn<AccountGroup, BigDecimal> actualColumn = new TableColumn<>(resources.getString("Column.Actual"));
actualColumn.setCellValueFactory(param -> {
if (param.getValue() != null) {
return new SimpleObjectProperty<>(budgetResultsModel.getResults(descriptor, param.getValue()).getChange());
}
return new SimpleObjectProperty<>(BigDecimal.ZERO);
});
actualColumn.setCellFactory(param -> new AccountGroupTableCell());
actualColumn.minWidthProperty().bind(columnWidth);
actualColumn.maxWidthProperty().bind(columnWidth);
actualColumn.setSortable(false);
actualColumn.resizableProperty().set(false);
headerColumn.getColumns().add(actualColumn);
final TableColumn<AccountGroup, BigDecimal> remainingColumn = new TableColumn<>(resources.getString("Column.Remaining"));
remainingColumn.setCellValueFactory(param -> {
if (param.getValue() != null) {
return new SimpleObjectProperty<>(budgetResultsModel.getResults(descriptor, param.getValue()).getRemaining());
}
return new SimpleObjectProperty<>(BigDecimal.ZERO);
});
remainingColumn.setCellFactory(param -> new AccountGroupTableCell());
// the max width is not bound to allow last column to grow and fill any voids
remainingColumn.minWidthProperty().bind(remainingColumnWidth);
remainingColumn.maxWidthProperty().bind(remainingColumnWidth);
remainingColumn.setSortable(false);
remainingColumn.resizableProperty().set(false);
headerColumn.getColumns().add(remainingColumn);
return headerColumn;
}
use of jgnash.engine.AccountGroup in project jgnash by ccavanaugh.
the class AbstractCrosstabReport method createTableModel.
@SuppressWarnings("ConstantConditions")
private ReportModel createTableModel() {
logger.info(rb.getString("Message.CollectingReportData"));
CurrencyNode baseCurrency = EngineFactory.getEngine(EngineFactory.DEFAULT).getDefaultCurrency();
List<Account> accounts = new ArrayList<>();
String sortOrder = sortOrderList.getSelectedItem().toString();
boolean needPercentiles = SORT_ORDER_BALANCE_DESC_WITH_PERCENTILE.equals(sortOrder);
for (AccountGroup group : getAccountGroups()) {
List<Account> list = getAccountList(AccountType.getAccountTypes(group));
boolean ascendingSortOrder = true;
if (!list.isEmpty()) {
if (list.get(0).getAccountType() == AccountType.EXPENSE) {
ascendingSortOrder = false;
}
}
if (SORT_ORDER_NAME.equals(sortOrder)) {
if (!showLongNamesCheckBox.isSelected()) {
list.sort(Comparators.getAccountByName());
} else {
list.sort(Comparators.getAccountByPathName());
}
} else if (SORT_ORDER_BALANCE_DESC.equals(sortOrder) || SORT_ORDER_BALANCE_DESC_WITH_PERCENTILE.equals(sortOrder)) {
list.sort(Comparators.getAccountByBalance(startDateField.getLocalDate(), endDateField.getLocalDate(), baseCurrency, ascendingSortOrder));
}
if (needPercentiles) {
BigDecimal groupTotal = BigDecimal.ZERO;
for (Account a : list) {
groupTotal = groupTotal.add(a.getBalance(startDateField.getLocalDate(), endDateField.getLocalDate(), baseCurrency));
}
BigDecimal sumSoFar = BigDecimal.ZERO;
for (Account a : list) {
sumSoFar = sumSoFar.add(a.getBalance(startDateField.getLocalDate(), endDateField.getLocalDate(), baseCurrency));
percentileMap.put(a, sumSoFar.doubleValue() / groupTotal.doubleValue());
}
}
accounts.addAll(list);
}
updateResolution();
// remove any account that will report a zero balance for all periods
if (hideZeroBalanceAccounts.isSelected()) {
Iterator<Account> i = accounts.iterator();
while (i.hasNext()) {
Account account = i.next();
boolean remove = true;
for (int j = 0; j < endDates.size(); j++) {
if (account.getBalance(startDates.get(j), endDates.get(j)).compareTo(BigDecimal.ZERO) != 0) {
remove = false;
break;
}
}
if (remove) {
i.remove();
}
}
}
// configure columns
List<ColumnInfo> columnsList = new LinkedList<>();
// accounts column
ColumnInfo ci = new AccountNameColumnInfo(accounts);
ci.columnName = rb.getString("Column.Account");
ci.headerStyle = ColumnHeaderStyle.LEFT;
ci.columnClass = String.class;
ci.columnStyle = ColumnStyle.STRING;
ci.isFixedWidth = false;
columnsList.add(ci);
for (int i = 0; i < dateLabels.size(); ++i) {
ci = new DateRangeBalanceColumnInfo(accounts, startDates.get(i), endDates.get(i), baseCurrency);
ci.columnName = dateLabels.get(i);
ci.headerStyle = ColumnHeaderStyle.RIGHT;
ci.columnClass = BigDecimal.class;
ci.columnStyle = ColumnStyle.BALANCE_WITH_SUM_AND_GLOBAL;
ci.isFixedWidth = true;
columnsList.add(ci);
}
// cross-tab total column
ci = new CrossTabAmountColumnInfo(accounts, baseCurrency);
ci.columnName = "";
ci.headerStyle = ColumnHeaderStyle.RIGHT;
ci.columnClass = BigDecimal.class;
ci.columnStyle = ColumnStyle.CROSSTAB_TOTAL;
ci.isFixedWidth = true;
columnsList.add(ci);
if (needPercentiles) {
ci = new PercentileColumnInfo(accounts);
ci.columnName = "Percentile";
ci.headerStyle = ColumnHeaderStyle.RIGHT;
ci.columnClass = String.class;
ci.columnStyle = ColumnStyle.CROSSTAB_TOTAL;
ci.isFixedWidth = true;
columnsList.add(ci);
}
// grouping column (last column)
ci = new GroupColumnInfo(accounts);
ci.columnName = "Type";
ci.headerStyle = ColumnHeaderStyle.CENTER;
ci.columnClass = String.class;
ci.columnStyle = ColumnStyle.GROUP;
ci.isFixedWidth = false;
columnsList.add(ci);
columns = columnsList.toArray(new ColumnInfo[columnsList.size()]);
return new ReportModel(accounts, baseCurrency);
}
Aggregations