our company wants to print staff card for our personnel so we prepared a template which contains a placeholder for each person's photo, name and department.
we have a database table that includes path to photo, name and department of each person.
I would like to know if there is possibility to loop through that table and add person data into card template and save it.
I'm using C#.Net but if you know a better solution for this reason I'd be glad to listen.

- 1,140
- 3
- 22
- 48
-
Save it as what? An image, a PDF file, XML? Actually it doesn't matter, really - yes! It is possible! – TaW Feb 17 '15 at 16:43
-
@TaW saving it as jpeg file would be great. can you help me more, a link or tutorial ? – mhesabi Feb 18 '15 at 05:29
-
Sure. But first tell us a little more about what you mean by _we prepared a template which contains a placeholder for each person's photo, name and department_. What is that template? Also an image? A set of measurements where each part shall go and size it shall have? Can you post a screenshot of that template? – TaW Feb 18 '15 at 06:28
-
@TaW thanks for helping. updated my Q and yes, the card template is an image (psd or jpeg) with some places that must be filled with employees information – mhesabi Feb 18 '15 at 07:04
-
I see that you have accepted the answer even before all my corrections went in. Note: I have just addded code to make the photo always have the right width on the template. – TaW Feb 18 '15 at 16:16
-
actually I was looking for a link to a tutorial at first but you gave me even better; a complete code and a very great answer which led me to the final solution. thank you a lot for your help and SO ofcourse – mhesabi Feb 19 '15 at 16:26
2 Answers
This is no problem at all using C# and GDI+
Here is the short version:
- Create a
Bitmap
of the right size and resolution - Measure the coordinates of the images and text you want to have on it
- Pull the data from your database
- Use
Graphics.DrawImage
andGraphics.DrawString
to create the graphics - Save in a format you like, preferably
PNG
as this will keep the text sharp
Here come the details:
- You need to calculate how many pixels your image should have. Since you want to be able to print it you should use at least 150dpi or 200dpi.
The Image you posted has no DPI setting and 1004x638 pixels; setting it to 150dpi results in a physical size of 170x108 mm. Let's assume that this is OK..
So we create a bitmap with these parameters:
Size keyCardSize = new Size (1004, 638);
float Dpi = 150f;
Bitmap bmp = new Bitmap(keyCardSize.Width, keyCardSize.Height);
bmp.SetResolution(Dpi, Dpi);
- The code below will use millimeters as the unit. You may want to change this to something else.
Looking at your template we see 6 images (logo, photo and 4 icons) and 7 chunks of text (name, position, dept. and four contact texts).
The basic commands for drawing an image or a text with a Graphics G
look like this:
G.DrawImage(bitmap, location);
G.DrawString(text, font, brush, location);
In our case this works fine for the logo and the photo since they are left aligned. All you need to do is to measure the positions and create the location points. Make sure you either create the images in the correct size&resolution or that you adapt the dpi to make up for differing pixel sizes!
Update: I have included code to adapt the photo's dpi
to make the width fit in the 30mm frame in the template. This assumes that the proportions are correct and/or that we care more about the width than the height.. If we need to match both, either get the proportions right or ask for a cropping code ;-)
Measuring the rest of our items is a little more complicated, since they all are right aligned. Here is an example how to do it for a string txt1:
SizeF s1 = G.MeasureString(txt1, font1, PointF.Empty, StringFormat.GenericTypographic);
G.DrawString(txt1, font1, brush1, new Point((int)(rightBorder - s1.Width), y1));
You can (and must) measure the top (Y
) of each location but the left (X
) must be calculated like above!
Note that you need to tell the measurement command the font you want to use; ignore the other params! After measuring the right border these commands will work fine with the necessary data and graphics objects..
- Pulling the data from your database. I assume you can do that! I further assume that you can change & expand the code below to fill the data fields and make
filename
dynamic with your records..
4&5. See this code example:
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();
//..
}
I hope this gets you going. If you have questions, feel free to ask..
Here is the rudimentary result:
An afterthought: You may want to simplify the whole code by using the template as the start: You can have the logo, the icons and the vertical bar all in place and only need to draw one image and the texts..!

- 53,122
- 8
- 69
- 111
-
Point((int)(rightBorder - s1.Width) what do you mean by rightBorder in this line? – Abdullah Malikyar Nov 10 '15 at 04:57
-
`Point((int)(rightBorder - s1.Width)` what do you mean by rightBorder in this line? – Abdullah Malikyar Nov 10 '15 at 04:59
-
In that example line I was speaking in general terms; in the later code I called it rBorder to make it a little shorter. It is, well, the right border of the paper in the chosen unit.. – TaW Nov 10 '15 at 06:41
-
So you mean the `full width of the paper - the length of the text - the right margin ` ? can align text ? irrespective of text length. – Abdullah Malikyar Nov 10 '15 at 09:01
-
Well, the forumla does contain the tect length, doesn't it? But there is a way to get automatic alignment with [StringFormat](http://stackoverflow.com/questions/32880669/how-many-spaces-does-t-use-in-c-sharp/32892371?s=2|0.0000#32892371). For this you need a (large enough) Rectangle that ends at the right border and the system will take care of the measuring and aligning.. – TaW Nov 10 '15 at 09:06
-
suppose i have a rectangle 300mm wide and i want all the text to have 100mm margin from the right border and the text length can vary, but i want all the texts to start right from 100mm from right border(i.e right after the margin). how can i achieve this? – Abdullah Malikyar Nov 10 '15 at 09:12
-
-
I am printing right-aligned, i am printing arabic text so it should be from right to left aligned. hope you got my point – Abdullah Malikyar Nov 10 '15 at 11:29
-
Unfortunately I'm neither accustomed with right-to-left ptrinting/drawing nor can I test it. So you will need to experiment a littel. The rectangle maybe should be (0,y,200,9999) and the format probably StringFormat fmt = new StringFormat() { Alignment = StringAlignment.Right} but I'm not sure here.. – TaW Nov 10 '15 at 12:31
-
Ok thanks for all the help so far i will try figuring it out myself – Abdullah Malikyar Nov 11 '15 at 04:39
Okay, just an idea may not work, but I thought I would throw something out there to maybe help!
How about you create a program that does as you say , loops the database. But for the Staff cards create a User interface with like a GraphicsBox, and a few text boxes; Create/use a print function on the Ui, make the window borderless for the printout.
Im not sure if this would work as i use C++ and never really thought of doing something like this but i got this from the top of my head give it ago you never know!
But then you would obviously be printing to a high quality plastic i assume, or is it getting laminated? Not that is really matters just interested :)

- 571
- 3
- 19