【问题标题】:Generate Staff Card生成员工卡
【发布时间】:2020-01-30 00:16:59
【问题描述】:

我们公司想为我们的员工打印员工卡,因此我们准备了一个模板,其中包含每个人的照片、姓名和部门的占位符。
我们有一个数据库表,其中包括每个人的照片路径、姓名和部门。
我想知道是否有可能遍历该表并将人员数据添加到卡片模板中并保存。
我正在使用 C#.Net,但如果您因此知道更好的解决方案,我很乐意倾听。

【问题讨论】:

  • 另存为什么?图像、PDF 文件、XML?其实没关系,真的——是的!有可能!
  • @TaW 将其保存为 jpeg 文件会很棒。你能帮我更多吗,链接或教程?
  • 当然。但首先请告诉我们更多关于您所说的我们准备了一个模板,其中包含每个人的照片、姓名和部门的占位符。那个模板是什么?还有头像?一组测量每个零件的位置和尺寸?你能张贴那个模板的截图吗?
  • @TaW 感谢您的帮助。更新了我的 Q,是的,卡片模板是一张图片(psd 或 jpeg),其中一些地方必须填写员工信息
  • 我看到您甚至在我进行所有更正之前就已经接受了答案。注意:我刚刚添加了代码以使照片在模板上始终具有正确的宽度。

标签: c# drawing


【解决方案1】:

使用C#和GDI+完全没问题

这是简短的版本:

  1. 创建一个大小和分辨率合适的Bitmap
  2. 测量您想要在其上放置的图像和文本的坐标
  3. 从数据库中提取数据
  4. 使用Graphics.DrawImageGraphics.DrawString 创建图形
  5. 以您喜欢的格式保存,最好是PNG,因为这样可以保持文本清晰

这里有详细信息:

  1. 您需要计算图像应该有多少像素。由于您希望能够打印它,您应该使用至少 150dpi 或 200dpi。

您发布的图片没有 DPI 设置和 1004x638 像素;将其设置为 150dpi 会导致物理尺寸为 170x108 毫米。让我们假设这没问题..

所以我们用这些参数创建一个位图:

Size keyCardSize = new Size (1004, 638);
float Dpi = 150f;
Bitmap bmp = new Bitmap(keyCardSize.Width, keyCardSize.Height);
bmp.SetResolution(Dpi, Dpi);
  1. 下面的代码将使用毫米作为单位。您可能希望将其更改为其他内容。

查看您的模板,我们看到 6 张图片(徽标、照片和 4 个图标)和 7 块文本(姓名、职位、部门和四个联系文本)。

使用Graphics G 绘制图像或文本的基本命令如下所示:

   G.DrawImage(bitmap, location);
   G.DrawString(text, font, brush, location);

在我们的例子中,这适用于徽标和照片,因为它们是左对齐的。您需要做的就是测量位置并创建定位点。确保您要么以正确的尺寸和分辨率创建图像调整 dpi 以弥补不同的像素尺寸!

更新:我已包含代码以调整照片的dpi,以使 宽度 适合模板中的 30 毫米框架。这假设比例是正确的和/或我们更关心宽度而不是高度。如果我们需要同时匹配两者,要么得到正确的比例,要么要求裁剪代码;-)

测量我们其余的项目有点复杂,因为它们都是右对齐的。下面是一个如何为字符串 txt1 执行此操作的示例:

SizeF s1 = G.MeasureString(txt1, font1, PointF.Empty, StringFormat.GenericTypographic);
G.DrawString(txt1, font1, brush1, new Point((int)(rightBorder - s1.Width), y1));

您可以(并且必须)测量每个位置的顶部 (Y),但左侧 (X) 必须像上面一样计算!

注意,你需要告诉测量命令你要使用的字体;忽略其他参数!测量右边界后,这些命令将与必要的数据和图形对象一起正常工作..

  1. 从数据库中提取数据。我想你可以做到这一点!我进一步假设您可以更改和扩展下面的代码以填充数据字段并使用您的记录使 filename 动态化..

4&5。请参阅此代码示例:


 private void Button_Click(object sender, EventArgs e)
 {
    string FontFamily = "Verdana";

    string fileName = "d:\\template.png";

    Size keyCardSize = new Size (1004, 638); // 170x108mm
    float Dpi = 150f;
    Bitmap bmp = new Bitmap(keyCardSize.Width, keyCardSize.Height);
    bmp.SetResolution(Dpi, Dpi);

    // test data:
    Bitmap photo = new Bitmap(@"D:\scrape\sousers\SOU_JonSkeet.jpeg");
    // I have measured the photo should be 30mm wide
    // so with 25.4mm to the inch we calculate a fitting dpi for it:  
    float photoDpi = photo.Width * 25.4f / 30f;
    photo.SetResolution(photoDpi , photoDpi );

    Font font1 = new Font(FontFamily, 23f);
    Font font2 = new Font(FontFamily, 12f);
    Font font3 = new Font(FontFamily, 14f);

    using (Graphics G = Graphics.FromImage(bmp))
    using (SolidBrush brush1 = new SolidBrush(Color.MediumVioletRed))
    using (SolidBrush brush2 = new SolidBrush(Color.Gray))
    {
        G.Clear(Color.White);
        G.InterpolationMode = InterpolationMode.HighQualityBicubic;
        G.PageUnit = GraphicsUnit.Millimeter;
        G.SmoothingMode = SmoothingMode.HighQuality;

        StringFormat sf = StringFormat.GenericTypographic;

        int lBorder= 10;
        int rBorder= 160;
        int y1 = 10;
        int y2 = 25;
        //..
        int y4 = 60;
        //..
        //G.DrawImage(logo, imgLoc1);
        G.DrawImage(photo, new Point(lBorder, y4));
        //G.DrawImage(img3, imgLoc3);
        //G.DrawImage(img4, imgLoc4);
        //G.DrawImage(img5, imgLoc5);


       // test data:
        string txt1 = "Jon Skeet";
        string txt2 = "C Sharp Evangelist";
        //..

        SizeF s1 = G.MeasureString(txt1, font1, PointF.Empty, sf);
        SizeF s2 = G.MeasureString(txt2, font2, PointF.Empty, sf);
        //..

        G.DrawString(txt1, font1, brush1, new Point((int)(rBorder- s1.Width), y1));
        G.DrawString(txt2, font2, brush2, new Point((int)(rBorder- s2.Width), y2));

        //G.DrawString(txt3, font2, brush2, txtLoc3);
        //..
        //G.DrawString(txt7, font3, brush2, txtLoc7);

        G.FillRectangle(brush1, new RectangleF(rBorder - 1.5f, 52f, 1.5f, 46f));

  }

  bmp.Save(fileName, ImageFormat.Png);

  font1.Dispose();
  font2.Dispose();
  font3.Dispose();

  photo.Dispose();
  //..
}

我希望这能让你继续前进。如果您有任何问题,请随时提问。。

这是初步的结果:

事后的想法:您可能希望通过使用模板作为开始来简化整个代码:您可以将徽标、图标和垂直条都放在适当的位置,只需要绘制一个图像和文本......!

【讨论】:

  • Point((int)(rightBorder - s1.Width) 这行中的rightBorder是什么意思?
  • Point((int)(rightBorder - s1.Width) 这一行中的 rightBorder 是什么意思?
  • 在该示例行中,我是笼统地说;在后面的代码中,我将其命名为 rBorder 以使其更短一些。它是所选单位中纸张的右边框..
  • 所以你的意思是full width of the paper - the length of the text - the right margin ?可以对齐文本吗?与文本长度无关。
  • 嗯,论坛确实包含 tect 长度,不是吗?但是有一种方法可以自动对齐StringFormat。为此,您需要一个(足够大)以右边界结束的矩形,系统将负责测量和对齐..
【解决方案2】:

好的,只是一个想法可能行不通,但我想我会抛出一些东西来可能会有所帮助!

您如何创建一个按您说的那样循环数据库的程序。但是为员工卡片创建一个带有图形框和一些文本框的用户界面;在 Ui 上创建/使用打印功能,使打印输出的窗口无边框。

我不确定这是否可行,因为我使用 C++ 并且从未真正想过做这样的事情,但我从头顶得到了这个,你永远不知道之前给它!

但是你显然会打印到我认为的高质量塑料上,还是被层压了?这不是真的很重要,只是感兴趣:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 2012-02-27
    • 1970-01-01
    • 2011-07-13
    • 2011-06-20
    相关资源
    最近更新 更多