我们就从页眉开始,页眉包含Logo、标题和标签三部分。
首先要给页眉定一个高度,这个高度还必需是固定,定得高则页眉和主体之间空白太多不美观,定少又有部分内容显示不出来,偏偏这个页眉中的内容是不固定,那只能用一个参数 headerHeight 来记录了。后面的页脚也一样用一个参数footerHeight来记录。
private float headerHeight = 0.0F;
private float footerHeight = 0.0F;
Logo部分大致包含一个Logo图片、企业名称、地址、电话、传真、邮箱和微信二维码,这些资料通过一个DataTable传递进来,然后通过AddLogo(DataTable dataTable, Boolean showLine)处理,保存到一个reportLogoString可变的字符序列里
private StringBuilder reportLogoString = new StringBuilder();
这个DataTable的数据后面还会用到,干脆就连公章、微信二维码、签名、人名、是不是审核一起传递进来,这个DataTable的结构如下:
DataTable dt = new DataTable();
dt.Columns.Add("OutletsLogo", Type.GetType("System.Byte[]"));
dt.Columns.Add("OutletsName", Type.GetType("System.String"));
dt.Columns.Add("OutletsAddress", Type.GetType("System.String"));
dt.Columns.Add("OutletsTel", Type.GetType("System.String"));
dt.Columns.Add("OutletsFax", Type.GetType("System.String"));
dt.Columns.Add("OutletsEmail", Type.GetType("System.String"));
dt.Columns.Add("OS", Type.GetType("System.Byte[]"));
dt.Columns.Add("SignatureImg", Type.GetType("System.Byte[]"));
dt.Columns.Add("EmployeeName", Type.GetType("System.String"));
dt.Columns.Add("Reviewed", Type.GetType("System.String"));
dt.Columns.Add("OutletsWeChat", Type.GetType("System.Byte[]"));
这个DataTable需要增加到DataSets节点中,名称为DataLogo,保存在_reportItemPatterns中,然后添加Logo图片、企业名称、地址、电话、传真、邮箱和微信二维码并保存到reportLogoString中,然后根据需要来增加一条分隔线。
需要注意设置左右边距、上边距和页眉高。
private List<ReportItemPattern> _reportItemPatterns = new List<ReportItemPattern>();
private StringBuilder reportLogoString = new StringBuilder();
private Boolean isSignature = true;
private Boolean isSignatureImg = false;
public void AddLogo(DataTable dataTable, Boolean showLine)
{
if (dataTable != null && dataTable.Rows.Count > 0)
{
if (headerHeight == 0) headerHeight += TopMargin;
var fields = new StringBuilder();
foreach (DataColumn dataColumn in dataTable.Columns)
{
fields.AppendFormat("<Field Name=\"{0}\"><DataField>{0}</DataField><rd:TypeName>" + dataColumn.DataType + "</rd:TypeName></Field>", dataColumn.ColumnName);
}
var dataSetName = "DataLogo";
var reportItemPattern = new ReportItemPattern();
reportItemPattern.Data = DynamicReportExtension.RemoveZeroData(dataTable);
reportItemPattern.DataSetName = dataSetName;
reportItemPattern.DataSetString = reportItemPattern.DataSetPattern.Replace("@DataSetName", dataSetName).Replace("@Fields", fields.ToString());
_reportItemPatterns.Add(reportItemPattern);
float logoWidth = pageWidth - leftMargin * 2 - leftMargin / 2;
float topPosition = topMargin;
float leftPosition = leftMargin + leftMargin / 2;
string imagesString = "";
if (dataTable.Rows[0]["OutletsLogo"] != DBNull.Value)
{
string imgPattern = " <Image Name=\"LogoImg\">" +
" <Source>Embedded</Source>" +
" <Value>LogoImg</Value>" +
" <MIMEType>image/png</MIMEType>" +
" <Sizing>FitProportional</Sizing>" +
" <Top>" + topPosition + "cm</Top>" +
" <Left>" + leftPosition + "cm</Left>" +
" <Height>1.6cm</Height>" +
" <Width>1.6cm</Width>" +
" <Style>" +
" <Border><Style>None</Style></Border>" +
" </Style>" +
" </Image>";
reportLogoString.Append(imgPattern);
leftPosition += 1.7F;
headerHeight += 1.7F;
logoWidth -= 1.7F;
imagesString += "<EmbeddedImage Name=\"LogoImg\"><MIMEType>image/png</MIMEType><ImageData>" + Convert.ToBase64String((Byte[])dataTable.Rows[0]["OutletsLogo"]) + "</ImageData></EmbeddedImage>";
}
if (dataTable.Rows[0]["OutletsWeChat"] != DBNull.Value)
{
string imgPattern = " <Image Name=\"WeChatImg\">" +
" <Source>Embedded</Source>" +
" <Value>WeChatImg</Value>" +
" <MIMEType>image/png</MIMEType>" +
" <Sizing>FitProportional</Sizing>" +
" <Top>" + topPosition + "cm</Top>" +
" <Left>" + (pageWidth - leftMargin - 1.5) + "cm</Left>" +
" <Height>1.5cm</Height>" +
" <Width>1.5cm</Width>" +
" <Style>" +
" <Border><Style>None</Style></Border>" +
" </Style>" +
" </Image>";
reportLogoString.Append(imgPattern);
logoWidth -= 1.6F;
imagesString += "<EmbeddedImage Name=\"WeChatImg\"><MIMEType>image/png</MIMEType><ImageData>" + Convert.ToBase64String((Byte[])dataTable.Rows[0]["OutletsWeChat"]) + "</ImageData></EmbeddedImage>";
}
Image imageOs = null;
Image imageSignature = null;
if (dataTable.Rows[0]["OS"] != DBNull.Value) imageOs = BytesToImage((Byte[])dataTable.Rows[0]["OS"]);
if (dataTable.Rows[0]["SignatureImg"] != DBNull.Value) imageSignature = BytesToImage((Byte[])dataTable.Rows[0]["SignatureImg"]);
if (dataTable.Rows[0]["Reviewed"].ToString().ToUpper() == "TRUE")
{
isSignatureImg = true;
Bitmap bitmap = CombinImage(imageOs, imageSignature, dataTable.Rows[0]["OutletsName"].ToString().Trim(), dataTable.Rows[0]["EmployeeName"].ToString().Trim(), fontString);
imagesString += "<EmbeddedImage Name=\"SignatureImg\"><MIMEType>image/png</MIMEType><ImageData>" + Convert.ToBase64String(ImageToBytes(bitmap)) + "</ImageData></EmbeddedImage>";
}
if (imagesString != "")
{
_docTemplate = _docTemplate.Replace("@LogoImageData", imagesString);
}
else
{
_docTemplate = _docTemplate.Replace("<EmbeddedImages>@LogoImageData</EmbeddedImages>", "");
}
if (dataTable.Rows[0]["OutletsName"].ToString() != "")
{
string namePattern = " <Textbox Name=\"LogoName\">" +
" <CanGrow>true</CanGrow>" +
" <KeepTogether>true</KeepTogether>" +
" <Paragraphs>" +
" <Paragraph>" +
" <TextRuns>" +
" <TextRun>" +
" <Value>" + dataTable.Rows[0]["OutletsName"].ToString() + "</Value>" +
" <Style><FontFamily>" + fontString + "</FontFamily><FontSize>16pt</FontSize></Style>" +
" </TextRun>" +
" </TextRuns>" +
" <Style>None</Style>" +
" </Paragraph>" +
" </Paragraphs>" +
" <rd:DefaultName>LogoName</rd:DefaultName>" +
" <Top>" + topPosition + "cm</Top>" +
" <Left>" + leftPosition + "cm</Left>" +
" <Height>1.0cm</Height>" +
" <Width>" + logoWidth + "cm</Width>" +
" <ZIndex>1</ZIndex>" +
" <Style>" +
" <VerticalAlign>Bottom</VerticalAlign>" +
" <Border><Style>None</Style></Border>" +
" <PaddingLeft>0pt</PaddingLeft>" +
" <PaddingRight>0pt</PaddingRight>" +
" <PaddingTop>0pt</PaddingTop>" +
" <PaddingBottom>0pt</PaddingBottom>" +
" </Style>" +
" </Textbox>";
reportLogoString.Append(namePattern);
topPosition += 1.0F;
if (headerHeight < 1.7F) headerHeight += 1.7F;
}
string address = "";
if (dataTable.Rows[0]["OutletsAddress"].ToString() != "") address = dataTable.Rows[0]["OutletsAddress"].ToString();
if (address != "")
{
if (dataTable.Rows[0]["OutletsTel"].ToString() != "") address += " " + dataTable.Rows[0]["OutletsTel"].ToString();
if (dataTable.Rows[0]["OutletsFax"].ToString() != "") address += " " + dataTable.Rows[0]["OutletsFax"].ToString();
if (dataTable.Rows[0]["OutletsEmail"].ToString() != "") address += " " + dataTable.Rows[0]["OutletsEmail"].ToString();
float fontHeight = 0.5F;
if (Graphics.FromHwnd(IntPtr.Zero).MeasureString(address, new Font(fontString, 8)).Width * 1.12 > MillimetersToPixelsWidth(logoWidth * 10) - 3)
{
fontHeight += 0.3F;
headerHeight += 0.3F;
}
string addrPattern = " <Textbox Name=\"LogoAddr\">" +
" <CanGrow>true</CanGrow>" +
" <KeepTogether>true</KeepTogether>" +
" <Paragraphs>" +
" <Paragraph>" +
" <TextRuns>" +
" <TextRun>" +
" <Value>" + address + "</Value>" +
" <Style><FontFamily>" + fontString + "</FontFamily><FontSize>8pt</FontSize></Style>" +
" </TextRun>" +
" </TextRuns>" +
" <Style>None</Style>" +
" </Paragraph>" +
" </Paragraphs>" +
" <rd:DefaultName>LogoAddr</rd:DefaultName>" +
" <Top>" + topPosition + "cm</Top>" +
" <Left>" + leftPosition + "cm</Left>" +
" <Height>" + fontHeight + "cm </Height>" +
" <Width>" + logoWidth + "cm</Width>" +
" <ZIndex>2</ZIndex>" +
" <Style>" +
" <VerticalAlign>Top</VerticalAlign>" +
" <Border><Style>None</Style></Border>" +
" <PaddingLeft>2pt</PaddingLeft>" +
" <PaddingRight>2pt</PaddingRight>" +
" <PaddingTop>0pt</PaddingTop>" +
" <PaddingBottom>2pt</PaddingBottom>" +
" </Style>" +
" </Textbox>";
reportLogoString.Append(addrPattern);
topPosition += fontHeight + 0.05F;
if (headerHeight < 1.7F) headerHeight += 1.7F;
}
if (topPosition > topMargin)
{
if (showLine)
{
string linePattern = " <Line Name=\"LineLogo\">" +
" <Top>" + topPosition + "cm</Top>" +
" <Left>" + leftMargin / 2 + "cm</Left>" +
" <Height>0.0cm</Height>" +
" <Width>" + (pageWidth - leftMargin) + "cm</Width>" +
" <ZIndex>3</ZIndex>" +
" <Style>" +
" <Border><Style>Solid</Style></Border>" +
" </Style>" +
" </Line>";
reportLogoString.Append(linePattern);
}
headerHeight += 0.1F;
topMargin = topPosition + 0.1F;
}
}
}
在这里面,还生成了一个签名、盖章的图片,后面会调用到。图章的大小根据需要设定。
public byte[] ImageToBytes(Image image)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] bytes = ms.GetBuffer();
ms.Close();
return bytes;
}
public Image BytesToImage(byte[] bytes)
{
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
Image image = Image.FromStream(ms);
ms.Close();
return image;
}
public static Bitmap CombinImage(Image imgOS, Image imgSignature, string outletsName, string employeeName, string fontString)
{
int width = 143;
int height = 143;
int top = 90;
if (imgOS != null)
{
if (imgOS.Width > 165)
{
width = 171;
height = 116;
top = 82;
}
}
if (imgSignature != null)
{
if (imgSignature.Height < top) top = height - imgSignature.Height + 10;
}
Bitmap bmp = new Bitmap(300, height + 20);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.Clear(Color.Transparent);
g.DrawLine(new Pen(Color.Black, 1), new Point(0, height - 10), new Point(300, height - 10));
if (outletsName != "") g.DrawString(outletsName, new Font(fontString, 12), new SolidBrush(Color.Black), (300 - g.MeasureString(outletsName, new Font(fontString, 12)).Width) / 2, height - 11);
if (imgSignature != null)
{
g.DrawImage(imgSignature, (300 - imgSignature.Width) / 2, top, imgSignature.Width, imgSignature.Height);
}
else
{
if (employeeName != "") g.DrawString(employeeName, new Font(fontString, 16), new SolidBrush(Color.Black), (300 - g.MeasureString(employeeName, new Font(fontString, 16)).Width) / 2, height - g.MeasureString(employeeName, new Font(fontString, 16)).Height - 10);
}
if (imgOS != null) g.DrawImage(imgOS, (300 - width) / 2, 1, width, height);
GC.Collect();
return bmp;
}
标签部分是不确定的,可以是多行单列或多行二列,数据好是通过一个DataTable传递进来。DataTable的结构为:
DataTable dt = new DataTable();
dt.Columns.Add("LeftName", Type.GetType("System.String"));
dt.Columns.Add("LeftValue", Type.GetType("System.String"));
dt.Columns.Add("RightName", Type.GetType("System.String"));
dt.Columns.Add("RightValue", Type.GetType("System.String"));
当需要使用一列标签时就只输入LeftName、LeftValue的值,RightName、RightValue留空;需要使用二列标签时则4个值都添加。
传递进来的数据用前面定义的标签格式生成节点,保存到reportLabelPatterns中,然后根据需要来增加一条分隔线。需要留意处理页眉高。
private List<string> reportLabelPatterns = new List<string>();
public void AddLabel(DataTable dataTable, Color color, Boolean showLine)
{
if (dataTable != null && dataTable.Rows.Count > 0)
{
if (headerHeight == 0) headerHeight += TopMargin;
float topPosition = topMargin;
float leftPosition = leftMargin;
float labelWidt = pageWidth - leftMargin * 2 - 0.31F;
float aWidth = labelWidt * 0.3F;
float bWidth = labelWidt * 0.7F;
float cWidth = labelWidt * 0.22F;
float dWidth = labelWidt * 0.23F;
if (dataTable.Columns.Count > 2)
{
labelWidt = pageWidth - leftMargin - 0.61F;
leftPosition = leftMargin / 2;
aWidth = labelWidt * 0.2F;
bWidth = labelWidt * 0.35F;
}
foreach (DataRow dataRow in dataTable.Rows)
{
var labelPattern = LabelPattern
.Replace("@TopPosition", topPosition.ToString())
.Replace("@TextboxName", reportLabelPatterns.Count.ToString())
.Replace("@FontString", fontString)
.Replace("@Color", color.Name.ToString())
.Replace("@NameText", dataRow[0].ToString())
.Replace("@NamePosition", leftPosition.ToString())
.Replace("@NameWidth", aWidth.ToString())
.Replace("@SplitPosition", (leftPosition + aWidth + 0.01F).ToString())
.Replace("@ValuePosition", (leftPosition + aWidth + 0.32F).ToString())
.Replace("@ValueWidth", bWidth.ToString());
if (dataRow[1].ToString().Trim() != "")
{
labelPattern = labelPattern.Replace("@ValueText", dataRow[1].ToString());
}
else
{
labelPattern = labelPattern.Replace("<Value>@ValueText</Value>", "<Value />");
}
reportLabelPatterns.Add(labelPattern);
if (dataTable.Columns.Count > 2)
{
labelPattern = LabelPattern
.Replace("@TopPosition", topPosition.ToString())
.Replace("@TextboxName", reportLabelPatterns.Count.ToString())
.Replace("@FontString", fontString)
.Replace("@Color", color.Name.ToString())
.Replace("@NameText", dataRow[2].ToString())
.Replace("@NamePosition", (leftPosition + aWidth + bWidth + 0.33F).ToString())
.Replace("@NameWidth", cWidth.ToString())
.Replace("@SplitPosition", (leftPosition + aWidth + bWidth + cWidth + 0.34F).ToString())
.Replace("@ValuePosition", (leftPosition + aWidth + bWidth + cWidth + 0.65F).ToString())
.Replace("@ValueWidth", dWidth.ToString());
if (dataRow[3].ToString().Trim() != "")
{
labelPattern = labelPattern.Replace("@ValueText", dataRow[3].ToString());
}
else
{
labelPattern = labelPattern.Replace("<Value>@ValueText</Value>", "<Value />");
}
reportLabelPatterns.Add(labelPattern);
}
topPosition += 0.5F;
headerHeight += 0.5F;
if (Graphics.FromHwnd(IntPtr.Zero).MeasureString(dataRow[1].ToString(), new Font(fontString, 9)).Width * 1.12 > MillimetersToPixelsWidth(bWidth * 10) - 3)
{
headerHeight += 0.3F;
}
}
if (showLine)
{
string linePattern = " <Line Name=\"LineLabel\">" +
" <Top>" + (topPosition + 0.1F) + "cm</Top>" +
" <Left>" + leftMargin / 2 + "cm</Left>" +
" <Height>0.0cm</Height>" +
" <Width>" + (pageWidth - leftMargin) + "cm</Width>" +
" <ZIndex>3</ZIndex>" +
" <Style>" +
" <Border><Style>Solid</Style></Border>" +
" </Style>" +
" </Line>";
reportLabelPatterns.Add(linePattern);
}
headerHeight += 0.2F;
topMargin = topPosition + 0.2F;
}
}
标题部分比较简单,设置好样式就行。可以是添加多行标题,保存到_reportTitlePatterns中,同样要设置页眉高。
private List<string> _reportTitlePatterns = new List<string>();
public void AddTitle(string title, int fontSize, string fontWeight, Color color, TextAlign textAlign, float height)
{
if (!string.IsNullOrEmpty(title))
{
if (headerHeight == 0) headerHeight += TopMargin;
var titlePattern = TitlePattern
.Replace("@TextboxName", _reportTitlePatterns.Count.ToString())
.Replace("@Title", title)
.Replace("@FontString", fontString)
.Replace("@FontSize", fontSize.ToString())
.Replace("@FontWeight", fontWeight)
.Replace("@Color", color.Name.ToString())
.Replace("@TextAlign", textAlign.ToString())
.Replace("@TopPosition", topMargin.ToString())
.Replace("@LeftPosition", leftMargin.ToString())
.Replace("@TextboxName", _reportTitlePatterns.Count.ToString())
.Replace("@Height", height.ToString())
.Replace("@Width", (pageWidth - leftMargin * 3).ToString());
_reportTitlePatterns.Add(titlePattern);
topMargin += height + 0.01F;
headerHeight += height + 0.01F;
}
}
页脚可以是多行的,保存到_reportPageFooter中,需要设置页脚的高度。
private List<string> _reportPageFooter = new List<string>();
public void AddPageFooter(string footerText, int fontSize, string fontWeight, Color color, TextAlign textAlign, float height)
{
if (!string.IsNullOrEmpty(footerText))
{
if (footerHeight == 0) footerHeight = 0.02F;
string footerPattern = " <Textbox Name=\"Footer" + _reportPageFooter.Count.ToString() + "\">" +
" <CanGrow>true</CanGrow>" +
" <KeepTogether>true</KeepTogether>" +
" <Paragraphs>" +
" <Paragraph>" +
" <TextRuns>" +
" <TextRun>" +
" <Value>" + footerText + "</Value>" +
" <Style><FontFamily>" + fontString + "</FontFamily><FontSize>" + fontSize.ToString() + "pt</FontSize><FontWeight>" + fontWeight + "</FontWeight><Color>" + color.Name.ToString() + "</Color></Style>" +
" </TextRun>" +
" </TextRuns>" +
" <Style><TextAlign>" + textAlign.ToString() + "</TextAlign></Style>" +
" </Paragraph>" +
" </Paragraphs>" +
" <rd:DefaultName>Footer" + _reportPageFooter.Count.ToString() + "</rd:DefaultName>" +
" <Top>" + footerHeight.ToString() + "cm</Top>" +
" <Left>" + leftMargin.ToString() + "cm</Left>" +
" <Height>" + height.ToString() + "cm </Height>" +
" <Width>" + (pageWidth - leftMargin * 2).ToString() + "cm</Width>" +
" <ZIndex>1</ZIndex>" +
" <Style>" +
" <VerticalAlign>Middle</VerticalAlign>" +
" <Border><Style>None</Style></Border>" +
" <PaddingLeft>2pt</PaddingLeft>" +
" <PaddingRight>2pt</PaddingRight>" +
" <PaddingTop>2pt</PaddingTop>" +
" <PaddingBottom>2pt</PaddingBottom>" +
" </Style>" +
" </Textbox>";
_reportPageFooter.Add(footerPattern);
footerHeight += height + 0.01F;
}
}