封裝 Microsoft.Reporting.WinForms.ReportViewer,提供:
public abstract class BaseReportForm : Form
{
protected ReportViewer ReportViewer { get; private set; }
public string ReportConfigFile { get; set; } // *.rps
public string QueryConfigFile { get; set; } // *.pcs
public string PrintConfigFile { get; set; } // *.rps (列印專用)
protected BaseReportForm()
{
ReportViewer = new ReportViewer { Dock = DockStyle.Fill };
Controls.Add(ReportViewer);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadReportConfig();
BindData();
ReportViewer.RefreshReport();
}
protected virtual void LoadReportConfig()
{
// 解析 *.rps XML,設定 ReportViewer.LocalReport.PageSettings、頁首頁尾文字等
}
protected abstract void BindData(); // 子類實作資料來源綁定
protected virtual void SetReportConfig(ReportConfig config)
{
// 子類覆寫動態設定頁首頁尾參數(公司名、操作員、列印日期、頁碼)
}
}
<?xml version="1.0" encoding="utf-8"?>
<ReportConfig>
<Title>銷售明細報表</Title>
<ColumnConfigFile>frmSalesReport</ColumnConfigFile> <!-- 對應 *.cls 欄位配置 -->
<PaperSize>
<Width>29.7</Width> <!-- CM -->
<Height>21</Height>
</PaperSize>
<Margins>
<Left>1.5</Left> <Top>1</Top> <Right>1.5</Right> <Bottom>1</Bottom>
</Margins>
<Landscape>true</Landscape>
<Header>
<Height>3</Height> <!-- CM -->
<Objects>
<Label>
<Key>Company</Key>
<Text></Text> <!-- 由程式動態填入 -->
<HAlign>Center</HAlign> <AutoCenter>true</AutoCenter>
<Font><Name>微軟正黑體</Name><Size>16</Size></Font>
<Location><X>0</X><Y>0.5</Y></Location>
<Size><Width>0</Width><Height>1</Height></Size>
</Label>
<Label>
<Key>Title</Key>
<Text></Text>
<HAlign>Center</HAlign> <AutoCenter>true</AutoCenter>
<Font><Name>微軟正黑體</Name><Size>14</Size></Font>
<Location><X>0</X><Y>1.5</Y></Location>
<Size><Width>0</Width><Height>0.8</Height></Size>
</Label>
<Label>
<Key>Operator</Key>
<Text>操作員:{0}</Text>
<HAlign>Left</HAlign> <Location><X>0.5</X><Y>2.5</Y></Location>
</Label>
<Label>
<Key>PrintDate</Key>
<Text>列印日期:{0:yyyy/MM/dd}</Text>
<HAlign>Right</HAlign> <AutoRight>true</AutoRight>
<Location><X>0</X><Y>2.5</Y></Location>
</Label>
</Objects>
</Header>
<Footer>
<Height>1</Height>
<Objects>
<Label>
<Key>Page</Key>
<Text>第 {PageNumber} 頁 / 共 {TotalPages} 頁</Text>
<HAlign>Right</HAlign> <AutoRight>true</AutoRight>
<Location><X>0</X><Y>0.2</Y></Location>
</Label>
</Objects>
</Footer>
</ReportConfig>
<Columns>
<Column><Key>OrderNo</Key><Text>訂單編號</Text><Width>3</Width><Align>Center</Align></Column>
<Column><Key>ProductName</Key><Text>商品名稱</Text><Width>6</Width><Align>Left</Align></Column>
<Column><Key>Qty</Key><Text>數量</Text><Width>1.5</Width><Align>Right</Align><Type>NumberColumn</Type><Formater>N0</Formater></Column>
<Column><Key>Amount</Key><Text>金額</Text><Width>2</Width><Align>Right</Align><Type>NumberColumn</Type><Formater>C2</Formater></Column>
<Column><Key>OrderDate</Key><Text>下單日期</Text><Width>2.5</Width><Align>Center</Align><Type>DateTimeColumn</Type><Formater>yyyy/MM/dd</Formater></Column>
</Columns>
public class SalesReportForm : BaseReportForm
{
public SalesReportForm()
{
ReportConfigFile = "frmSalesReport.rps";
QueryConfigFile = "frmSalesReport.pcs";
}
protected override void BindData()
{
// 1. 取得查詢條件(從 QueryConfig 對應的查詢視窗回傳)
var qb = QueryBuilder.FromConfig(QueryConfigFile); // 假設有解析器
// 2. 查詢資料
var dal = new SalesDAL();
var dt = dal.GetSalesData(qb); // 回傳 DataTable
// 3. 設定報表資料來源
ReportViewer.LocalReport.DataSources.Clear();
ReportViewer.LocalReport.DataSources.Add(new ReportDataSource("SalesDataSet", dt));
// 4. 設定報表內嵌 RDLC 路徑
ReportViewer.LocalReport.ReportEmbeddedResource = "MyApp.Reports.SalesReport.rdlc";
// 5. 動態設定頁首參數
SetReportConfig(ReportConfig);
}
protected override void SetReportConfig(ReportConfig config)
{
base.SetReportConfig(config);
config.Header.FindObject("Company")?.SetText(AppContext.CompanyName);
config.Header.FindObject("Title")?.SetText("2024 年度銷售明細");
config.Header.FindObject("Operator")?.SetText(string.Format("操作員:{0}", AppContext.UserName));
config.Header.FindObject("PrintDate")?.SetText(string.Format("列印日期:{0:yyyy/MM/dd}", DateTime.Today));
}
}
ReportDataSource 名稱一致(如 "SalesDataSet")。TextBox,Value 設為 =Parameters!Company.Value 等參數。=Globals!PageNumber / =Globals!TotalPages。=Sum(Fields!Amount.Value)。// 直接列印(無預覽)
ReportViewer.PrintDialog(); // 或 PrintToPrinter()
// 匯出 PDF
byte[] pdf = ReportViewer.LocalReport.Render("PDF");
File.WriteAllBytes("Report.pdf", pdf);
// 匯出 Excel
byte[] excel = ReportViewer.LocalReport.Render("EXCELOPENXML"); // .xlsx
File.WriteAllBytes("Report.xlsx", excel);
BaseReportForm 以 配置檔驅動 + 抽象基類 + RDLC 模板 三位一體,實現報表開發標準化:版面調整改 XML、資料邏輯寫子類、樣式調整改 RDLC。配合 *.cls 欄位配置複用,新增報表只需建立三個 XML + 一個 RDLC + 一個子類,大幅降低維護成本。