مطالب
نحوه ذخیره شدن متن در فایل‌های PDF
تبدیل بی عیب و نقص یک فایل PDF (انواع و اقسام آن‌ها) به متن قابل درک بسیار مشکل است. در ادامه بررسی خواهیم کرد که چرا.
برخلاف تصور عموم، ساختار یک صفحه PDF شبیه به یک صفحه فایل Word نیست. این صفحات درحقیقت نوعی Canvas برای نقاشی هستند. در این بوم نقاشی، شکل، تصویر، متن و غیره در مختصات خاصی قرار خواهند گرفت. حتی کلمه «متن» می‌تواند به صورت سه حرف در سه مختصات خاص یک صفحه PDF نقاشی شود. برای درک بهتر این مورد نیاز است سورس یک صفحه PDF را بررسی کرد.

نحوه استخراج سورس یک صفحه PDF

using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace TestReaders
{
    class Program
    {
        static void writePdf()
        {
            using (var document = new Document(PageSize.A4))
            {
                var writer = PdfWriter.GetInstance(document, new FileStream("test.pdf", FileMode.Create));
                document.Open();

                document.Add(new Paragraph("Test"));

                PdfContentByte cb = writer.DirectContent;
                BaseFont bf = BaseFont.CreateFont();
                cb.BeginText();
                cb.SetFontAndSize(bf, 12);
                cb.MoveText(88.66f, 367);
                cb.ShowText("ld");
                cb.MoveText(-22f, 0);
                cb.ShowText("Wor");
                cb.MoveText(-15.33f, 0);
                cb.ShowText("llo");
                cb.MoveText(-15.33f, 0);
                cb.ShowText("He"); 
                cb.EndText();

                PdfTemplate tmp = cb.CreateTemplate(250, 25);
                tmp.BeginText();
                tmp.SetFontAndSize(bf, 12);
                tmp.MoveText(0, 7);
                tmp.ShowText("Hello People");
                tmp.EndText();
                cb.AddTemplate(tmp, 36, 343);
            }

            Process.Start("test.pdf");
        }

        private static void readPdf()
        {
            var reader = new PdfReader("test.pdf");
            int intPageNum = reader.NumberOfPages;
            for (int i = 1; i <= intPageNum; i++)
            {
                byte[] contentBytes = reader.GetPageContent(i);
                File.WriteAllBytes("page-" + i + ".txt", contentBytes);
            }
            reader.Close();
        }

        static void Main(string[] args)
        {
            writePdf();
            readPdf();
        }
    }
}
فایل PDF تولیدی حاوی سه عبارت کامل و مفهوم می‌باشد:


اگر علاقمند باشید که سورس واقعی صفحات یک فایل PDF را مشاهده کنید، نحوه انجام آن توسط کتابخانه iTextSharp به صورت فوق است.
هرچند متد GetPageContent آرایه‌ای از بایت‌ها را بر می‌گرداند، اما اگر حاصل نهایی را در یک ادیتور متنی باز کنیم، قابل مطالعه و خواندن است. برای مثال، سورس مثال فوق (محتوای فایل page-1.txt تولید شده) به نحو زیر است:
q
BT
36 806 Td
0 -18 Td
/F1 12 Tf
(Test)Tj
0 0 Td
ET
Q
BT
/F1 12 Tf
88.66 367 Td
(ld)Tj
-22 0 Td
(Wor)Tj
-15.33 0 Td
(llo)Tj
-15.33 0 Td
(He)Tj
ET
q 1 0 0 1 36 343 cm /Xf1 Do Q
و تفسیر این عملگرها به این ترتیب است:
SaveGraphicsState(); // q
BeginText(); // BT
MoveTextPos(36, 806); // Td
MoveTextPos(0, -18); // Td
SelectFontAndSize("/F1", 12); // Tf
ShowText("(Test)"); // Tj
MoveTextPos(0, 0); // Td
EndTextObject(); // ET
RestoreGraphicsState(); // Q
BeginText(); // BT
SelectFontAndSize("/F1", 12); // Tf
MoveTextPos(88.66, 367); // Td
ShowText("(ld)"); // Tj
MoveTextPos(-22, 0); // Td
ShowText("(Wor)"); // Tj
MoveTextPos(-15.33, 0); // Td
ShowText("(llo)"); // Tj
MoveTextPos(-15.33, 0); // Td
ShowText("(He)"); // Tj
EndTextObject(); // ET
SaveGraphicsState(); // q
TransMatrix(1, 0, 0, 1, 36, 343); // cm
XObject("/Xf1"); // Do
RestoreGraphicsState(); // Q
همانطور که ملاحظه می‌کنید کلمه Test به مختصات خاصی انتقال داده شده و سپس به کمک اطلاعات فونت F1، ترسیم می‌شود.
تا اینجا استخراج متن از فایل‌های PDF ساده به نظر می‌رسد. باید به دنبال Tj گشت و حروف مرتبط با آن‌را ذخیره کرد. اما در مورد «ترسیم» عبارات hello world و hello people اینطور نیست. عبارت hello world به حروف متفاوتی تقسیم شده و سپس در مختصات مشخصی ترسیم می‌گردد. عبارت hello people به صورت یک شیء ذخیره شده در قسمت منابع فایل PDF، بازیابی و نمایش داده می‌شود و اصلا در سورس صفحه جاری وجود ندارد.
این تازه قسمتی از نحوه عملکرد فایل‌های PDF است. در فایل‌های PDF می‌توان قلم‌ها را مدفون ساخت. همچنین این قلم‌ها نیز تنها زیر مجموعه‌ای از قلم اصلی مورد استفاده هستند. برای مثال اگر عبارت Test قرار است نمایش داده شود، فقط اطلاعات T، e و s در فایل نهایی PDF قرار می‌گیرند. به علاوه امکان تغییر کلی شماره Glyph متناظر با هر حرف نیز توسط PDF writer وجود دارد. به عبارتی الزامی نیست که مشخصات اصلی فونت حتما حفظ شود.
شاید بعضی از PDFهای فارسی را دیده باشید که پس از کپی متن آن‌ها در برنامه Adobe reader و سپس paste آن در جایی دیگر، متن حاصل قابل خواندن نیست. علت این است که نحوه ذخیره سازی قلم مورد استفاده کاملا تغییر کرده است و برای بازیابی متن اینگونه فایل‌ها، استفاده از OCR ساده‌ترین روش است. برای نمونه در این قلم جدید مدفون شده، دیگر شماره کاراکتر 0x41 مساوی A نیست. بنابر سلیقه PDF writer این شماره به Glyph دیگری انتساب داده شده و چون قلم و مشخصات هندسی Glyph مورد استفاده در فایل PDF ذخیره می‌شود، برای نمایش این نوع فایل‌ها هیچگونه مشکلی وجود ندارد. اما متن آن‌ها به سادگی قابل بازیابی نیست.
نظرات مطالب
فعال سازی قسمت ارسال فایل و تصویر ویرایشگر آنلاین RedActor در ASP.NET MVC
خیر. احتمالا به این علت که آنچنان مرسوم نیست از چندین قلم در وب استفاده شود، منهای CSS اصلی سایت و تعریف قلم‌های اصلی برای هدرها و امثال آن. به علاوه قلم متن نمایش داده شده در صفحات باید تابع CSS سایت باشد نه ادیتور آن.
ولی در کل می‌تونید براش افزونه بنویسید تا اینکار را انجام دهد.
بازخوردهای پروژه‌ها
مشکل در ایجاد CustomHeader در نسخه جدید
من با توجه به نسخه 1.4 برای ایجاد CustomHeader کد زیر را نوشته بودم
 public PdfPTable RenderingReportHeader(Document pdfDoc, PdfWriter pdfWriter, IList<SummaryCellData> summaryData)
    {
        var httpCookie = HttpContext.Current.Request.Cookies["FinancialMarine"];
          if (httpCookie != null)
          {
              int requestId = int.Parse(httpCookie.Value);
              var ctx = new clearanceEntities();

              var item = (from d in ctx.CLEARANCE_ITEMS
                          where d.REQUEST_ID == requestId
                          select d).FirstOrDefault();
              if (item != null)
              {
                 
                 
                


                  string imagepath = HttpRuntime.AppDomainAppPath + "tir.JPG";
                  string imagepath2 = HttpRuntime.AppDomainAppPath + "tir2.JPG";

                  var fontPath = AppPath.ApplicationPath + "\\Fonts\\BNAZANIN.TTF";
                  //Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
                  var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                  var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);

                  PdfPTable table = new PdfPTable(numColumns: 3);

                  table.WidthPercentage = 100;
                  table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  table.ExtendLastRow = false;

                  Image img = Image.GetInstance(imagepath);
                  Image img2 = Image.GetInstance(imagepath2);

                  PdfPCell c = new PdfPCell(img);
                  c.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  c.Border = 0;


                  table.AddCell(c);

                  c = new PdfPCell(img2);
                  c.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  c.Border = 0;
                  c.Padding = 5;
                  table.AddCell(c);

                  ////////////////////////////////////////////////////////////////////////
                  PdfPTable table2 = new PdfPTable(numColumns: 2);
                  table2.WidthPercentage = 100;

                  table2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  table2.ExtendLastRow = false;

                  PdfPCell cell2 = new PdfPCell(new Phrase("تاریخ:", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  cell2 = new PdfPCell(new Phrase(" ", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  cell2 = new PdfPCell(new Phrase("شماره: ", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  cell2 = new PdfPCell(new Phrase("TST/F/91-4641 ", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  cell2 = new PdfPCell(new Phrase("پیوست: ", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  cell2 = new PdfPCell(new Phrase("مدارک ضمیمه ", tahomaFont));
                  cell2.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell2.Border = 0;
                  table2.AddCell(cell2);

                  var cell5 = new PdfPCell(table2);
                  cell5.Colspan = 3;
                  cell5.Border = 0;
                  table.AddCell(cell5);
                  ////////////////////////////////////////////////////////////////////////////////////
                  PdfPCell cell = new PdfPCell(new Phrase("شرکت", tahomaFont));
                  cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell.Padding = 10;
                  cell.Border = 0;
                  cell.Colspan = 3;
                  table.AddCell(cell);
                  cell = new PdfPCell(new Phrase("اداره محترم بازرگانی / تدارکات کالا", tahomaFont));
                  cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell.Padding = 10;
                  cell.Border = 0;
                  cell.Colspan = 3;
                  table.AddCell(cell);

                  cell = new PdfPCell(new Phrase("با سلام", tahomaFont));
                  cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell.Padding = 10;
                  cell.Border = 0;
                  cell.Colspan = 3;
                  table.AddCell(cell);

                  cell = new PdfPCell(new Phrase("با احترام به شرح زیر یک فقره صورتحساب مربوط به ترخیص محمولات آن شرکت جهت اطلاع و صدور دستور مقتضی بحضورتان ایفاد می‌گردد.", tahomaFont));
                  cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell.Padding = 10;
                  cell.Border = 0;
                  cell.Colspan = 3;
                  table.AddCell(cell);


                  ////////////////////////////////////////////////////////////////
                  
                  PdfPTable table3 = new PdfPTable(numColumns: 6);
                  table3.WidthPercentage = 100;

                  table3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  table3.ExtendLastRow = false;

                  PdfPCell cell3 = new PdfPCell(new Phrase("کشتی/کامیون", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(item.CLEARANCE_REQUEST.SHIP_NAME + " " + item.CLEARANCE_REQUEST.TRAVEL_NO, tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(" تعداد و نوع بسته بندی", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(item.QUANTITY.ToString(CultureInfo.InvariantCulture) + " " + item.PACKING_TYPES.PACKING_NAME, tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(" شماره پروانه", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(item.CLEARANCE_REQUEST.PERMIT_NO, tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase("شماره بارنامه ", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);


                  cell3 = new PdfPCell(new Phrase(item.CLEARANCE_REQUEST.WAYBILL_NO, tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(" وزن(کیلوگرم)", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(item.TARE_WEIGHT.ToString(CultureInfo.InvariantCulture), tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(" شماره درخواست", tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell3 = new PdfPCell(new Phrase(item.CLEARANCE_REQUEST.REQUEST_NO, tahomaFont));
                  cell3.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                  cell3.Border = 0;
                  table3.AddCell(cell3);

                  cell = new PdfPCell(table3);
                  cell.Colspan = 3;
                  cell.Border = 0;

                  table.AddCell(cell);
                  return table;
              }
          }
        return null;
        
    }
ولی حال که از نسخه 1.5 استفاده می‌کنم دیگه نمی‌تونم مقدار Return تابع RenderingReportHeader را برابر tableدر کد بالا قرار دهم.

ممنون





مطالب
نمایش علایم مختلف در گزارشات و تهیه لیست قلم‌های نصب شده در سیستم توسط PdfReport
دو مثال جدید به سورس‌های PdfReport اضافه شده است:
الف) Samples\PdfReportSamples\ZapfDingbatsSymbols
تعاریف قلم توکاری به نام Adobe Zapf Dingbats در iTextSharp وجود دارد که جهت نمایش انواع و اقسام علایم در فایل‌های PDF می‌تواند بکارگرفته شود. این قلم توکار توسط قالبی به نام Symbol در PdfReport قابل استفاده است:
                    column.ColumnItemsTemplate(template =>
                    {
                        template.Symbol(data =>
                        {
                            if (Enum.IsDefined(typeof(AdobeZapfDingbats), data))
                            {
                                return (AdobeZapfDingbats)data;
                            }
                            return AdobeZapfDingbats.BallotX;
                        });
                    });
در اینجا data مقدار سلول جاری پیش از رندر شدن است. بر این اساس تنها کافی است انتخابی را انجام داده و یکی از مقادیر enum ایی به نام AdobeZapfDingbats را بازگردانیم.

دریافت فایل PDF خروجی حاصل:
ZapfDingbatsSymbols.pdf

ب) Samples\PdfReportSamples\PersianFontsListToPdf
در این مثال لیست تمام فونت‌های شروع شده با b که در سیستم نصب شده‌اند، تهیه می‌شود. برای اینکار یک قالب سفارشی سلول به نام FontsListCellTemplate تهیه شده است. ساختار آن هم بسیار ساده است. بر اساس اطلاعات ردیف جاری، متن و نام قلم مورد نظر را دریافت کرده و اطلاعات نهایی را نمایش می‌دهد.

دریافت فایل PDF خروجی حاصل:
  FontsListToPdfSample.pdf
پاسخ به بازخورد‌های پروژه‌ها
استفاده از فونت های مختلف در گزارش
بله مربوط به Header سفارشی است. ممنون برای Header سفارشی هم من رفتم کد زیر رو نوشتم درست شد
 var fontPath = AppPath.ApplicationPath + "\\Fonts\\BNAZANIN.TTF";
            //Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
        var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);
ولی اینجا دیگه نمی‌تونم دو فونت یعنی یک فونت برای فارسی و یک فونت برای انگلیسی تعریف کنم؟
نظرات مطالب
WF:Windows Workflow #1
با سلام
آیا کتاب فارسی در زمینه WF در بازار موجود می‌باشد و ممنون می‌شم دوستان در این زمینه دست به قلم شده و مطالبی در زمینه یادگیری آن منتشر کنند. با تشکر
مطالب
نمایش درصد پیشرفت، Watermark و گزارشات چند ستونی در PdfReport
گزارشی را در نظر بگیرید با این نیازها:
می‌خواهیم
الف) یک Watermark قطری را بر روی تمام صفحات گزارش ظاهر کنیم.
ب) عدد‌های درصد پیشرفت یک ستون را به صورت میله‌ای نمایش دهیم.
ج) در هر صفحه بجای اینکه یک جدول، اطلاعات را نمایش دهد و تمام صفحه را پر کند، دو جدول در دو ستون کنار هم اینکار را انجام دهند تا در حین چاپ گزارش، در میزان تعداد صفحات مصرفی صرفه جویی صورت گیرد.
د) مقادیر true با چک مارک و موارد false با علامت ضربدر نمایش داده شوند.

یک چنین شکلی در نهایت مد نظر است:


روش انجام کار را توسط کتابخانه PdfReport در ادامه بررسی خواهیم کرد.
ابتدا کلاس مدل زیر را در نظر بگیرید:
namespace PdfReportSamples.Models
{
    public class Task
    {
        public int Id { set; get; }
        public string Name { set; get; }
        public int PercentCompleted { set; get; }
        public bool IsActive { set; get; }
    }
}
به این ترتیب یک کلاس فعالیت تعریف شده است که در آن نام فعالیت، درصد پیشرفت و همچنین درجریان بودن آن قابل تنظیم است. از این کلاس جهت تهیه منبع داده گزارش استفاده می‌شود:
using System;
using System.Collections.Generic;
using System.Drawing;
using iTextSharp.text;
using PdfReportSamples.Models;
using PdfRpt;
using PdfRpt.Core.Contracts;
using PdfRpt.Core.Helper;
using PdfRpt.FluentInterface;

namespace PdfReportSamples.ProgressReport
{
    public class ProgressReportPdfReport
    {
        private IPdfFont getWatermarkFont()
        {
            var watermarkFont = new GenericFontProvider(
                                        AppPath.ApplicationPath + "\\fonts\\irsans.ttf",
                                        Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf");
            watermarkFont.Color = BaseColor.LIGHT_GRAY;
            watermarkFont.Size = 50;
            return watermarkFont;
        }

        public IPdfReportData CreatePdfReport()
        {
            return new PdfReport().DocumentPreferences(doc =>
            {
                doc.RunDirection(PdfRunDirection.RightToLeft);
                doc.Orientation(PageOrientation.Portrait);
                doc.PageSize(PdfPageSize.A4);
                doc.DocumentMetadata(new DocumentMetadata { Author = "Vahid", Application = "PdfRpt", Keywords = "Test", Subject = "Test Rpt", Title = "Test" });
                doc.DiagonalWatermark(new DiagonalWatermark
                {
                    Text = "نمایش درصد پیشرفت",
                    RunDirection = PdfRunDirection.RightToLeft,
                    Font = getWatermarkFont()
                });
            })
            .DefaultFonts(fonts =>
            {
                fonts.Path(AppPath.ApplicationPath + "\\fonts\\irsans.ttf",
                                  Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf");
            })
            .PagesFooter(footer =>
            {
                footer.DefaultFooter(PersianDate.ToPersianDateTime(DateTime.Now, "/", true));
            })
            .PagesHeader(header =>
            {
                header.DefaultHeader(defaultHeader =>
                {
                    defaultHeader.Message("گزارش جدید ما");
                    defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png");
                });
            })
            .MainTableTemplate(template =>
            {
                template.BasicTemplate(BasicTemplate.SilverTemplate);
            })
            .MainTablePreferences(table =>
            {
                table.ColumnsWidthsType(TableColumnWidthType.Relative);
                table.MultipleColumnsPerPage(new MultipleColumnsPerPage
                {
                    ColumnsGap = 20,
                    ColumnsPerPage = 2,
                    ColumnsWidth = 250,
                    IsRightToLeft = true,
                    TopMargin = 7
                });
            })
            .MainTableDataSource(dataSource =>
            {
                var listOfRows = new List<Task>();
                var rnd = new Random();
                for (int i = 0; i < 400; i++)
                {
                    listOfRows.Add(new Task
                    {
                        Id = rnd.Next(1000, 10000),
                        Name = "Task" + i,
                        PercentCompleted = rnd.Next(1, 100),
                        IsActive = rnd.Next(0, 2) == 1 ? true : false
                    });
                }
                dataSource.StronglyTypedList<Task>(listOfRows);
            })
            .MainTableColumns(columns =>
            {
                columns.AddColumn(column =>
                {
                    column.PropertyName("rowNo");
                    column.IsRowNumber(true);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(0);
                    column.Width(1);
                    column.HeaderCell("ردیف", captionRotation: 90);
                });

                columns.AddColumn(column =>
                {
                    column.PropertyName<Task>(x => x.Id);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(1);
                    column.Width(2);
                    column.HeaderCell("شماره فعالیت");
                });

                columns.AddColumn(column =>
                {
                    column.PropertyName<Task>(x => x.Name);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(2);
                    column.Width(3);
                    column.HeaderCell("فعالیت");
                });

                columns.AddColumn(column =>
                {
                    column.PropertyName<Task>(x => x.PercentCompleted);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(3);
                    column.Width(3);
                    column.HeaderCell("درصد پیشرفت");
                    column.ColumnItemsTemplate(template =>
                    {
                        template.ProgressBar(progressBarColor: Color.SkyBlue, showPercentText: true);
                        template.DisplayFormatFormula(obj =>
                        {
                            if (obj == null) return "% 0";
                            return "% " + obj.ToString();
                        });
                    });
                });

                columns.AddColumn(column =>
                {
                    column.PropertyName<Task>(x => x.IsActive);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(4);
                    column.Width(2);
                    column.HeaderCell("در جریان");
                    column.ColumnItemsTemplate(template =>
                    {
                        template.Checkmark(checkmarkFillColor: Color.Green, crossSignFillColor: Color.DarkRed);
                    });
                });
            })
            .MainTableEvents(events =>
            {
                events.DataSourceIsEmpty(message: "There is no data available to display.");
            })
            .Export(export =>
            {
                export.ToExcel();
            })
            .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\ProgressReportSample.pdf"));
        }
    }
}

توضیحات:

- همانطور که در کدهای فوق ملاحظه می‌کنید، برای تعریف یک watermark قطری در سراسر سند تولیدی، نیاز است در متد DocumentPreferences، تنظیمات DiagonalWatermark را مشخص کرد:
doc.DiagonalWatermark(new DiagonalWatermark
                {
                    Text = "نمایش درصد پیشرفت",
                    RunDirection = PdfRunDirection.RightToLeft,
                    Font = getWatermarkFont()
                });
در اینجا Text، متنی است که نمایش داده خواهد شد. تنظیم PdfRunDirection.RightToLeft برای نمایش صحیح متون فارسی الزامی است. همچنین این watermark نیاز به قلم مناسب و متفاوتی نسبت به قلم‌های پیش فرض گزارش نیز دارد:
        private IPdfFont getWatermarkFont()
        {
            var watermarkFont = new GenericFontProvider(
                                        AppPath.ApplicationPath + "\\fonts\\irsans.ttf",
                                        Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf");
            watermarkFont.Color = BaseColor.LIGHT_GRAY;
            watermarkFont.Size = 50;
            return watermarkFont;
        }
قلم‌هایی از جنس IPdfFont را توسط کلاس توکار GenericFontProvider به نحوی که ملاحظه می‌کنید می‌توان ایجاد کرد.

- برای ستون بندی گزارش باید به متد MainTablePreferences رجوع نمود. در اینجا می‌توان تنظیمات دقیق ستون‌های گزارش را مشخص کرد:
table.MultipleColumnsPerPage(new MultipleColumnsPerPage
                {
                    ColumnsGap = 20,
                    ColumnsPerPage = 2,
                    ColumnsWidth = 250,
                    IsRightToLeft = true,
                    TopMargin = 7
                });
برای مثال در اینجا 2 ستون در هر صفحه تعریف شده است (ColumnsPerPage). فاصله بین این ستون‌ها 20 است (ColumnsGap). عرض هر ستون 250 درنظر گرفته شده (ColumnsWidth) و همچنین توسط تنظیم IsRightToLeft، سبب خواهیم شد تا جداول از راست به چپ شروع و در صفحه نمایش داده شوند. (اگر به شماره ردیف‌ها در شکل ابتدای بحث دقت کنید، ردیف 1 در سمت راست صفحه قرار دارد).

- برای نمایش درصد پیشرفت در یک سلول خاص تنها کافی است قالب مخصوص آن‌را انتخاب و مقدار دهی کنیم:
                    column.ColumnItemsTemplate(template =>
                    {
                        template.ProgressBar(progressBarColor: Color.SkyBlue, showPercentText: true);
                        template.DisplayFormatFormula(obj =>
                        {
                            if (obj == null) return "% 0";
                            return "% " + obj.ToString();
                        });
                    });
قالب از پیش تعریف شده ProgressBar، مقدار سلول جاری را دریافت و آن‌را تبدیل به یک میله افقی درصد پیشرفت می‌کند. همچنین در اینجا توسط DisplayFormatFormula، یک علامت درصد هم به متنی که قرار است نمایش داده شود، اضافه کرده‌ایم.

- نمایش چک مارک و علامت ضربدر نیز به همین منوال است. باید قالب مناسبی را برای آن انتخاب و اعمال کرد:
                    column.ColumnItemsTemplate(template =>
                    {
                        template.Checkmark(checkmarkFillColor: Color.Green, crossSignFillColor: Color.DarkRed);
                    });
قالب Checkmark نیز جزو قالب‌های از پیش تعریف شده PdfReport است و بر اساس گرافیک برداری کار می‌کند.
نظرات مطالب
روش صحیح تعریف قلم در iTextSharp
سپاس از شما مشکل مقدار null برطرف میشه با این تغییر ، منتها فونت خاص ذکر شده Register نمیشه و از کش FontFactory بازیابی نمیشه.
   public iTextSharp.text.Font GetBNazanin()
        {

            var fontName = "BNazanin";
            var fontPath = Path.Combine(_hostingEnvironment.WebRootPath + @"\css\font\BNazanin\BNazanin.ttf");

            if (!FontFactory.IsRegistered(fontName))// به درستی کار می‌کند و در صورت وجود از کش می‌خواند
            {
                FontFactory.Register(fontPath);
            }

            return FontFactory.GetFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        }

  public iTextSharp.text.Font GetIRANSans()
        {
            var fontName = "IRANSansWeb(FaNum)_Medium";
            var fontPath = Path.Combine(_hostingEnvironment.WebRootPath + @"\css\font\IRANSansWeb(FaNum)_Medium.ttf");
          
            if (!FontFactory.IsRegistered(fontName))// always false
            {
                FontFactory.Register(fontPath);
            }
            return FontFactory.GetFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        }

 
نظرات مطالب
تهیه‌ی کارت با فرمت PDF با استفاده از کتابخانه iTextSharp
سلام.. بنده این کد رو نوشتم ولی اصلا اون سلول ایمیج رو در نظر نمیگیره.هرکاری میکنم اصلا نشون نمیده.. دلیلش چیه؟
var infoTable = new PdfPTable(6)
            {
                WidthPercentage = 100,
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                ExtendLastRow = false,
                SpacingBefore = 15,
                
            };

            infoTable.DefaultCell.Border = 2;

            infoTable.AddCell(new PdfPCell(new Phrase("اطلاعات شناسنامه ای", tfont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 15,
                Colspan=2
            });
            infoTable.AddCell(new PdfPCell(new Phrase("اطلاعات خانوادگی", tfont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 15,
                Colspan = 2
            });
            infoTable.AddCell(new PdfPCell(new Phrase("اطلاعات دانشگاهی", tfont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 15,
                Colspan = 2
            });

           
            var universityLogoImage = Image.GetInstance(imgPath);
            universityLogoImage.ScaleAbsolute(30, 30);  
//این عکس رو اصلا نشون نمیده
            topTable.AddCell(new PdfPCell(universityLogoImage)
            {
                HorizontalAlignment = Element.ALIGN_CENTER,
                Border = 2,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("وضعیت تاهل:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0][22].ToString() == "0" ? "مجرد" : "متاهل", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("کد تحصیلی:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0][0].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });


            infoTable.AddCell(new PdfPCell(new Phrase("تحصیلات همسر:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["wife_edu"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("شماره پرونده:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["t_parvande_num"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("تحصیلات پدر:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["father_edu"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("کد مرکز خدمات:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["bime_code"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase("شغل پدر:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["father_job"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });
            infoTable.AddCell(new PdfPCell(new Phrase("پایه قبولی:", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });

            infoTable.AddCell(new PdfPCell(new Phrase(dt.Rows[0]["enter_paye"].ToString(), docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 2,
                PaddingBottom = 10,
            });
            infoTable.AddCell(new PdfPCell(new Phrase("", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 0
            });

            infoTable.AddCell(new PdfPCell(new Phrase("", docFont))
            {
                RunDirection = PdfWriter.RUN_DIRECTION_RTL,
                HorizontalAlignment = Element.ALIGN_LEFT,
                Border = 0
            });
int[] infoTableColumnsWidth = { 20, 15, 20, 15,20,15 };

            infoTable.SetWidths(infoTableColumnsWidth);

            doc.Add(infoTable);
لازم به ذکره که من قبلش یه جدول سه ستونه درست کردم و داخلش یه لوگو گذاشتم که اون به خوبی چاپ میشه ولی این اصلا!