Report Generator Table Formatting

57 visualizzazioni (ultimi 30 giorni)
dpb
dpb il 9 Dic 2025 alle 16:59
Modificato: dpb il 11 Dic 2025 alle 17:00
I have the following function that works to add the table into a defined hole in an MS Word template; the content is all as expected excepting the formatting isn't quite as would like and have not been able to figure out how to get the last couple of details as desired.
Specifically, the
headerStyle ={ Bold(true), ...
};
...
t.Header.Style=headerStyle;
doesn't work to set the header to a bold font, nor does the similar code work for the footer.
Secondly, the entire table is outlined but the outline of the header and footer is missing...there are two rows in the table content section for which I do not want a row separator line; but do want the header and footer outlines. I don't see why that isn't what is instructed to do with
headerStyle ={ Bold(true), ...
Border("single"), ...
};
tableStyle = { Width("80%"), ...
Border("single"), ...
RowSep("none"), ...
ColSep("none") ...
};
footerStyle = { Bold(true), ...
Border("single"), ...
ColSep("none") ...
};
The full function follows...I didn't want to put the actual data out for public view so didn't attach the output document.
Hopefully, somebody understands this well enough to be able to know what magic incantations to take; found a formal table example in the doc from which this was copied, but none of the examples I could find ever don't show every row separator.
function addReportSummaryTable(donordata,yr)
% Annual summary table
corpus=donordata.corpus;
expendables=donordata.expends;
headerStyle ={ Bold(true), ...
};
tableStyle = { Width("80%"), ...
Border("single"), ...
RowSep("none"), ...
ColSep("none") ...
};
footerStyle = { Bold(true), ...
Border("single"), ...
ColSep("none") ...
};
entriesStyle = {FontFamily("Calibri"), ...
FontSize("11pt")};
headerContent=[{'Fund Summary'} compose('Fiscal Year %d',[yr-1 yr])];
bodyContent =[[{'Endowment (principal)'} cellstr(num2currency(corpus))];
[{'Expendable (income and contributions'} cellstr(num2currency(expendables))]];
totals=corpus+expendables;
footerContent = [{'Total fund balance'} cellstr(num2currency(totals))];
tableContent = [headerContent; bodyContent; footerContent];
t= FormalTable(tableContent);
t.Style=tableStyle;
t.Header.Style=headerStyle;
t.TableEntriesHAlign = "right";
t.TableEntriesStyle = [t.TableEntriesStyle, entriesStyle];
g=TableColSpecGroup();
s=TableColSpec();
s.Style={HAlign('left')};
g.ColSpecs=s;
t.ColSpecGroups=g;
t.HAlign = "center";
append(rpt, t);
end
  2 Commenti
Kevin Holly
Kevin Holly il 9 Dic 2025 alle 19:53
I just used some fake data. I will look into this. I need to take care of some things and then I will look at this soon.
donordata = table;
donordata.corpus = rand(2,1);
donordata.expends = rand(2,1);
yr = 2012;
addReportSummaryTable(donordata,yr)
function addReportSummaryTable(donordata,yr)
import mlreportgen.report.*
import mlreportgen.dom.*
rpt = Report('Annual Report', 'pdf');
open(rpt);
% Annual summary table
corpus=donordata.corpus;
expendables=donordata.expends;
headerStyle ={ Bold(true), ...
};
tableStyle = { Width("80%"), ...
Border("single"), ...
RowSep("none"), ...
ColSep("none") ...
};
footerStyle = { Bold(true), ...
Border("single"), ...
ColSep("none") ...
};
entriesStyle = {FontFamily("Calibri"), ...
FontSize("11pt")};
headerContent=[{'Fund Summary'} compose('Fiscal Year %d',[yr-1 yr])];
bodyContent =[[{'Endowment (principal)'} cellstr(num2currency(corpus))];
[{'Expendable (income and contributions'} cellstr(num2currency(expendables))]];
totals=corpus+expendables;
footerContent = [{'Total fund balance'} cellstr(num2currency(totals))];
tableContent = [headerContent; bodyContent; footerContent];
t= FormalTable(tableContent);
t.Style=tableStyle;
t.Header.Style=headerStyle;
t.TableEntriesHAlign = "right";
t.TableEntriesStyle = [t.TableEntriesStyle, entriesStyle];
g=TableColSpecGroup();
s=TableColSpec();
s.Style={HAlign('left')};
g.ColSpecs=s;
t.ColSpecGroups=g;
t.HAlign = "center";
append(rpt, t);
close(rpt);
end
function output = num2currency(number)
for ii = 1:length(number)
output{ii} = horzcat('$',num2str(number(ii)));
end
end
dpb
dpb il 9 Dic 2025 alle 22:00
Modificato: dpb il 9 Dic 2025 alle 22:28
num2currency([-1234.34 50000 0]).'
ans = 3×1 string array
"($1,234.34)" "$50,000.00" "$ - "
function currency=num2currency(X,N)
% num2currency Convert numbers to character representation as USD currency
% C = num2currency(X) converts a the array(X) to its USD representation C
% with two decimal digits.
%
% C = num2currency(X,N) converts a the matrix(X) to its USD representation C
% rounded to N decimal digits of precision as numerical rounding by the
% runtime i/o library, not necessarily bankers rounding.
%
% At present, the currency symbol is fixed as USD and always shown.
nc = java.text.DecimalFormat.getCurrencyInstance; % java currency instance in local locale
if nargin>1
if nc.getMaximumFractionDigits~=N, nc.setMaximumFractionDigits(N); end
end
currency=arrayfun(@(v) string(nc.format(v)),X);
% fixup to return "$ -" for zero -- pad to max length of values in array
ix=find(X==0);
if isempty(ix), return, end
L=max(strlength(currency(X>0))); % max of nonnegative to align $
currency(ix)="$"+blanks(L-1);
for i=ix
currency{i}(end-2)='-';
end
end

Accedi per commentare.

Risposta accettata

Kevin Holly
Kevin Holly il 9 Dic 2025 alle 20:09
Modificato: Kevin Holly il 9 Dic 2025 alle 22:31
You need to define the Formaltable with 3 inputs. Header, Body, and Footer, respectfully
t= FormalTable(headerContent, bodyContent, footerContent);
donordata = table;
donordata.corpus = rand(2,1);
donordata.expends = rand(2,1);
yr = 2012;
addReportSummaryTable(donordata,yr)
function addReportSummaryTable(donordata,yr)
import mlreportgen.report.*
import mlreportgen.dom.*
rpt = Report('Annual Report', 'pdf');
open(rpt);
% Annual summary table
corpus=donordata.corpus;
expendables=donordata.expends;
headerStyle ={ Bold(true)};
tableStyle = { Width("80%"), ...
Border("single"), ...
RowSep("none"), ...
ColSep("none") ...
};
footerStyle = { Bold(true), ...
Border("single"), ...
ColSep("none") ...
};
entriesStyle = {FontFamily("Calibri"), ...
FontSize("11pt")};
headerContent=[{'Fund Summary'} compose('Fiscal Year %d',[yr-1 yr])];
bodyContent =[[{'Endowment (principal)'} cellstr(num2currency(corpus))];
[{'Expendable (income and contributions'} cellstr(num2currency(expendables))]];
totals=corpus+expendables;
footerContent = [{'Total fund balance'} cellstr(num2currency(totals))];
% tableContent = [headerContent; bodyContent; footerContent];
t= FormalTable(headerContent, bodyContent, footerContent);
t.Style=tableStyle;
t.Header.Style=[t.Header.Style,headerStyle];
t.Footer.Style=[t.Footer.Style,footerStyle];
t.TableEntriesHAlign = "right";
t.TableEntriesStyle = [t.TableEntriesStyle, entriesStyle];
g=TableColSpecGroup();
s=TableColSpec();
s.Style={HAlign('left')};
g.ColSpecs=s;
t.ColSpecGroups=g;
t.HAlign = "center";
append(rpt, t);
close(rpt);
end
function output = num2currency(number)
for ii = 1:length(number)
output{ii} = horzcat('$',num2str(number(ii)));
end
end

Più risposte (1)

Taylor
Taylor il 9 Dic 2025 alle 21:01
Your “header” and “footer” rows are actually part of the body. FormalTable(tableContent) treats the whole array as the body. The Header and Footer objects exist, but they’re empty—so styling t.Header.Style (or t.Footer.Style) doesn’t affect the first/last rows you assembled. Build the table with separate sections:t = FormalTable(headerContent, bodyContent, footerContent);
Bold needs to be applied to the entries, not just the section container. For a TableHeader/TableFooter, use TableEntriesStyle (e.g., {Bold(true)}) to style the text inside the cells; Header.Style/Footer.Style applies to the section, and formats that don’t apply there are ignored.
RowSep('none') at the table level suppresses separators everywhere—including the rules under the header and above the footer. Use section‑level RowSep so the body has no separator while the header/footer still draw theirs.
With ColSep('none') and no row separators, you won’t see a box around those sections unless you add borders to the header/footer entries themselves (entry‑level borders override table/section separators).
  11 Commenti
Kevin Holly
Kevin Holly il 11 Dic 2025 alle 14:24
@dpb So, I discover that the below code does work. It actually changes the vertical alignment - I verified in Word, although it did not look like it when I did it yesterday. The problem was that there was a space underneath the text due to line spacing being multiple instead of single. I was able to fix this by adding a OuterMargin Style
Previous:
for i = 1:t.Header.NRows
r = t.Header.row(i);
for j = 1:r.NEntries
e = r.Entries(j);
e.Style = [e.Style {VAlign("bottom")}]; % Ensure vertical alignment is set to bottom
end
end
Fixed linespace with OuterMargin:
for i = 1:t.Header.NRows
r = t.Header.row(i);
for j = 1:r.NEntries
e = r.Entries(j);
e.Style = [e.Style {VAlign("bottom"), OuterMargin("0pt", "0pt","0pt","0pt")}];
end
end
dpb
dpb il 11 Dic 2025 alle 15:27
Modificato: dpb il 11 Dic 2025 alle 17:00
@Kevin Holly -- thanks a bunch! I hadn't realized about the line spacing; I'm not sure, but I may be able to fix that in the template with the paragraph style. My Word expertise beyond just typing into it and giving it to somebody else to clean up is near zero so I didn't think about there being something there causing the boundaries to be larger than the displayed text because of the line spacing.
Really appreciate you taking the time and effort to figure this out.

Accedi per commentare.

Tag

Prodotti


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by