【Spire.PDF】绘制柱状图,兼容性强,可自定义数据

C#写了一个绘制柱状图的方法,只需传入参数即可,自动绘制

先看看效果

【Spire.PDF】绘制柱状图,兼容性强,可自定义数据_第1张图片

 

柱状的宽度自动调整

可自定义绘制位置,柱状图大小,数据

可自定义柱状图标题,X轴和Y轴描述信息

当X轴名称较长时,可以设置旋转一定的角度
 

 

全部代码

    public class ReportTest
    {
        /// 
        /// 初始化
        /// 
        public void Init()
        {
            Doc = new PdfDocument();
            Doc.PageSettings.Margins.All = 0;//设置边距为0
            Doc.Pages.Add(); Doc.Pages.RemoveAt(0);//删除第一页,因为有水印
            Page = Doc.Pages.Add();
        }

        PdfDocument Doc;
        PdfPageBase Page;

        /// 
        /// 绘制柱状图
        /// 
        /// 
        public void DrawHistogram(HistogramModel model)
        {
            RectangleF loc = model.Location;
            List data = model.Data;

            int maxCount = data.Max(d => d.Count);
            int ratio = (int)Math.Ceiling((float)maxCount / 5);

            var familyName = "宋体";
            var Font12 = new PdfTrueTypeFont(new Font(familyName, 12, FontStyle.Regular), true);
            var Font10 = new PdfTrueTypeFont(new Font(familyName, 10, FontStyle.Regular), true);
            var Font8 = new PdfTrueTypeFont(new Font(familyName, 8, FontStyle.Regular), true);
            //背景颜色,浅黄色
            var bgColor = new PdfSolidBrush(ColorTranslator.FromHtml("#ECE9D8"));
            var fontColorBlack = new PdfSolidBrush(Color.Black);
            //柱状颜色
            var fontColorRed = new PdfSolidBrush(Color.Red);
            //柱状备注颜色
            var fontColorColumnar = new PdfSolidBrush(ColorTranslator.FromHtml("#FFFFE0"));
            //绘制背景
            Page.Canvas.DrawRectangle(bgColor, loc);

            //深灰色笔
            PdfPen lineColorPen = new PdfPen(ColorTranslator.FromHtml("#76746C"));
            //黑色笔
            PdfPen blackColorPen = new PdfPen(Color.Black);

            //横竖都分为8个单元格,内边距为1个单元格,表格占6个单元格,一个单元格的宽度和高度可能不同
            SizeF cellSize = new SizeF(loc.Width / 8, loc.Height / 8);
            //每个数据所占宽度,包含1/3的间距和2/3的内容
            float cellSizeEach = cellSize.Width * 6 / data.Count;
            float cellSizeEach1_3 = cellSizeEach / 3;
            float cellSizeEach2_3 = cellSizeEach1_3 * 2;
            //单元格高度
            float cellSizeHeight = cellSize.Height;
            //原点
            PointF yd = new PointF(loc.X + cellSize.Width, loc.Y + loc.Height - cellSize.Height);

            //绘制标题
            DrawText(page: Page, location: new PointF(loc.X, loc.Y + 3), font: Font12,
                alignment: PdfTextAlignment.Center, colWidth: loc.Width, rowHeight: 17f, contents: model.Title);

            //横线
            for (int i = 0; i < 7; i++)
            {
                float x1 = yd.X;
                float y = loc.Y + cellSize.Height + i * cellSize.Height;

                Page.Canvas.DrawLine(lineColorPen, x1, y, loc.X + loc.Width - cellSize.Width, y);
            }

            //绘制X轴描述
            DrawText(page: Page, location: new PointF(yd.X - cellSize.Width, loc.Y + 5), font: Font10,
                alignment: PdfTextAlignment.Right, colWidth: cellSize.Width, rowHeight: 17f, contents: model.XDescription);

            //绘制Y轴描述
            DrawText(page: Page, location: new PointF(loc.X + loc.Width - cellSize.Width + 5, loc.Y + loc.Height - cellSize.Height - 10), font: Font10,
                alignment: PdfTextAlignment.Left, colWidth: cellSize.Width, rowHeight: 17f, contents: model.YDescription);

            string[] contents = new string[7];
            for (int i = 0; i < 7; i++)
            {
                contents[i] = (6 - i) * ratio + "";
            }
            //绘制数量描述
            DrawText(page: Page, location: new PointF(yd.X - cellSize.Width, loc.Y + cellSizeHeight / 2), font: Font8,
                alignment: PdfTextAlignment.Right, colWidth: cellSize.Width - 5, rowHeight: cellSizeHeight, contents: contents);

            //竖线
            for (int i = 0; i < 7; i++)
            {
                float x = loc.X + cellSize.Width + i * cellSize.Width;
                float y2 = yd.Y;

                Page.Canvas.DrawLine(lineColorPen, x, loc.Y + cellSize.Height, x, y2);
            }

            //绘制
            for (int index = 0; index < data.Count; index++)
            {
                float ydSpacingX = yd.X + cellSizeEach1_3 * (index + 1) + cellSizeEach2_3 * index;
                float count = data[index].Count;
                float height = ratio == 0 ? 0 : cellSize.Height * (count / ratio);

                RectangleF rect = new RectangleF(ydSpacingX, yd.Y - height, cellSizeEach2_3, height);

                //避免柱状过宽
                if (rect.Width > cellSize.Width)
                {
                    //居中
                    rect.X += (rect.Width - cellSize.Width) / 2;
                    //调整大小,最大宽度
                    rect.Width = cellSize.Width;

                }

                float rectWidth = rect.Width + 20;
                float rectX = rect.X - 10;
                //X轴描述是否倾斜
                if (model.IsXDescriptionSlant == false)
                {
                    //绘制Y轴描述
                    DrawText(page: Page, location: new PointF(rectX, rect.Y + rect.Height), font: Font8,
                        alignment: PdfTextAlignment.Center, colWidth: rectWidth, rowHeight: 17f, contents: data[index].Description);
                }
                else
                {
                    #region 绘制Y轴描述 DrawString
                    float rectTran = rect.X + 5;

                    //保存当前状态
                    Page.Canvas.Save();
                    //设置旋转原点
                    Page.Canvas.TranslateTransform(rectTran, rect.Y + rect.Height);
                    //旋转20度
                    Page.Canvas.RotateTransform(20);
                    //设置位置大小
                    PointF rectPointF = new PointF(0, 0);
                    SizeF rectSizeF = new SizeF(50, 20);
                    RectangleF rectStr = new RectangleF(rectPointF, rectSizeF);
                    Page.Canvas.DrawString(data[index].Description, Font8, fontColorBlack, rectStr);
                    //恢复上次状态
                    Page.Canvas.Restore();
                    //备注:通过TranslateTransform设置旋转原点,然后通过DrawString绘制时,只需设置坐标为0,0即可
                    #endregion 绘制Y轴描述 DrawString
                }

                if (count != -1 && height >= 0)
                {
                    //绘制柱状
                    Page.Canvas.DrawRectangle(blackColorPen, fontColorRed, rect);
                }

                if (count >= 0)
                {
                    //绘制数量
                    DrawText(page: Page, location: new PointF(rectX, rect.Y - 15), font: Font8,
                       alignment: PdfTextAlignment.Center, colWidth: rectWidth, rowHeight: 17f, contents: data[index].Count.ToString());
                }
            }
        }

        /// 
        /// 绘制文本,为了统一居中
        /// 
        /// 页面
        /// 绘制位置
        /// 字体
        /// 左右对齐方式
        /// 列宽度
        /// 行高度
        /// 内容
        private void DrawText(PdfPageBase page, PointF location, PdfTrueTypeFont font, PdfTextAlignment alignment, float colWidth, float rowHeight, params string[] contents)
        {
            var Grid = new PdfGrid();
            var col = Grid.Columns.Add();
            Grid.Style.CellPadding = new PdfPaddings(0, 0, 0, 0);
            Grid.Style.CellSpacing = 0;
            Grid.Style.Font = font;
            col.Width = colWidth;//列宽

            for (int i = 0; i < contents.Length; i++)
            {
                var GridRow = Grid.Rows.Add();
                GridRow.Height = rowHeight;
                var PdfGridCell = GridRow.Cells[0];
                PdfGridCell.StringFormat = new PdfStringFormat(alignment, PdfVerticalAlignment.Middle);//对齐方式
                PdfGridCell.Value = contents[i];//绘制的文本
                PdfGridCell.Style.Font = font;//字体
                PdfGridCell.Style.TextBrush = new PdfSolidBrush(Color.Black);
            }

            //设置表格无边框
            PdfBorders borders = new PdfBorders { All = new PdfPen(Color.Transparent, 0.1f) };
            foreach (PdfGridRow row in Grid.Rows)
            {
                foreach (PdfGridCell cell in row.Cells)
                {
                    cell.Style.Borders = borders;
                }
            }
            Grid.Draw(page, location);//绘制的位置
        }

        /// 
        /// 保存
        /// 
        public void Save()
        {
            //保存
            string path = Path.Combine(Environment.CurrentDirectory, "Histograms");
            string name = DateTime.Now.ToString("yyyyMMddHHmmss");
            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }
            string fname = Path.Combine(path, name + ".pdf");
            Doc.SaveToFile(fname);
            Doc.Close();
            //打开
            Process.Start(fname);
        }
    }

    /// 
    /// 柱状图参数
    /// 
    public class HistogramModel
    {
        /// 
        /// 标题
        /// 
        public string Title { get; set; }
        /// 
        /// 位置
        /// 
        public RectangleF Location { get; set; }
        /// 
        /// X轴描述
        /// 
        public string XDescription { get; set; }
        /// 
        /// Y轴描述
        /// 
        public string YDescription { get; set; }
        /// 
        /// 数据
        /// 
        public List Data { get; set; }
        /// 
        /// X轴描述是否倾斜
        /// 
        public bool IsXDescriptionSlant { get; set; } = false;
    }

    /// 
    /// 柱状图数据模型
    /// 
    public class HistogramDataModel
    {
        public int Count { get; set; }
        public string Description { get; set; }
    }

使用

var test = new ReportTest();
test.Init();

List data = new List()
{
    new HistogramDataModel() { Count = 10, Description = "项目1" },
    new HistogramDataModel() { Count = 14, Description = "项目2" },
    new HistogramDataModel() { Count = 16, Description = "项目3" },
    new HistogramDataModel() { Count = 8, Description = "项目4" },
    new HistogramDataModel() { Count = 20, Description = "项目5" },

};
RectangleF loc = new RectangleF(new PointF(50, 50), new SizeF(400, 180));
test.DrawHistogram(new HistogramModel()
{
    Title = $"xxx统计柱状图1",
    Location = loc,
    XDescription = "数量",
    YDescription = "项目",
    Data = data,
    IsXDescriptionSlant = false
});

List data2 = new List()
{
    new HistogramDataModel() { Count = 30, Description = "项目名称1" },
    new HistogramDataModel() { Count = 10, Description = "项目名称2" },
    new HistogramDataModel() { Count = 50, Description = "项目名称3" },
    new HistogramDataModel() { Count = 45, Description = "项目名称4" },
    new HistogramDataModel() { Count = 32, Description = "项目名称5" },
    new HistogramDataModel() { Count = 25, Description = "项目名称6" },
    new HistogramDataModel() { Count = 53, Description = "项目名称7" },
    new HistogramDataModel() { Count = 23, Description = "项目名称8" },
    new HistogramDataModel() { Count = 46, Description = "项目名称9" },
    new HistogramDataModel() { Count = 33, Description = "项目名称10" },
};
RectangleF loc2 = new RectangleF(new PointF(50, 280), new SizeF(480, 200));
test.DrawHistogram(new HistogramModel()
{
    Title = $"xxx统计柱状图2",
    Location = loc2,
    XDescription = "数量",
    YDescription = "项目",
    Data = data2,
    IsXDescriptionSlant = true
});

test.Save();

效果

【Spire.PDF】绘制柱状图,兼容性强,可自定义数据_第2张图片

你可能感兴趣的:(Spire.PDF,报告,PDF,Spire.Pdf,C#,.NET)