Showing posts with label PDF. Show all posts
Showing posts with label PDF. Show all posts

Generate password protected pdf file dynamically in Asp.net


Description:-

Here we will create Password protected Pdf file Dynamically from Gridview Data. PDF File is very useful to read data and we can see clearly in Pdf file. So we can Generate Pdf File Dynamically and set Password as default when we create dynamically in server. Here is the simple code to achieve this functionality in dot net.

Create Table:-

CREATE TABLE [dbo].[Employee](
      [Number] [int] IDENTITY(1,1) NOT NULL,
      [Name] [varchar](50) NOT NULL,
      [Gender] [varchar](50) NOT NULL,
      [Email] [varchar](50) NOT NULL,
      [MobileNumber] [bigint] NOT NULL,
      [Bdate] [date] NULL,
 CONSTRAINT [PK_Employeee] PRIMARY KEY CLUSTERED
(
      [Number] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
 
Default.aspx:-

<div>
   <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#CCCCCC" BorderStyle="None" BorderWidth="1px" CellPadding="4" ForeColor="Black" GridLines="Horizontal" Height="123px" Width="594px">
      <Columns>
         <asp:BoundField DataField="Name" HeaderText="Name" ItemStyle-Width="80px">
            <HeaderStyle HorizontalAlign="Left" />
            <ItemStyle Width="80px" VerticalAlign="Middle"></ItemStyle>
         </asp:BoundField>
         <asp:BoundField DataField="Gender" HeaderText="Gender" ItemStyle-Width="80px">
            <HeaderStyle HorizontalAlign="Left" />
            <ItemStyle Width="80px" ></ItemStyle>
         </asp:BoundField>
         <asp:BoundField DataField="Email" HeaderText="Email" ItemStyle-Width="80px">
            <HeaderStyle HorizontalAlign="Left" />
            <ItemStyle Width="80px"></ItemStyle>
         </asp:BoundField>
         <asp:BoundField DataField="MobileNumber" HeaderText="MobileNumber" ItemStyle-Width="60px">
            <HeaderStyle HorizontalAlign="Left" />
            <ItemStyle Width="60px"></ItemStyle>
         </asp:BoundField>
         <asp:BoundField DataField="BDate" HeaderText="BDate" ItemStyle-Width="100px">
            <HeaderStyle HorizontalAlign="Left" />
            <ItemStyle Width="120px"></ItemStyle>
         </asp:BoundField>
      </Columns>
      <FooterStyle BackColor="#CCCC99" ForeColor="Black" />
      <HeaderStyle BackColor="#333333" ForeColor="White" Font-Bold="True"></HeaderStyle>
      <PagerStyle BackColor="White" ForeColor="Black" HorizontalAlign="Right" />
      <SelectedRowStyle BackColor="#CC3333" Font-Bold="True" ForeColor="White" />
      <SortedAscendingCellStyle BackColor="#F7F7F7" />
      <SortedAscendingHeaderStyle BackColor="#4B4B4B" />
      <SortedDescendingCellStyle BackColor="#E5E5E5" />
      <SortedDescendingHeaderStyle BackColor="#242121" />
   </asp:GridView>
   <br />
   <asp:Button ID="btnExport" runat="server" Text="Export To PDF" OnClick="ExportToPDF" />
</div>

Default.aspx.cs:-

Now Go to Code behind and Create Method for Bind Gridview when page load first time in browser. And Call in Page_Load () method.

private void BindGrid()
{
    string strConnString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
    using (SqlConnection con = new SqlConnection(strConnString))
    {
        using (SqlCommand cmd = new SqlCommand("select * FROM Employee"))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt = new DataTable())
                {
                    sda.Fill(dt);
                    GridView1.DataSource = dt;
                    GridView1.DataBind();
                }
            }
        }
    }
}

Page_load () method when page call first time in browser or else it is not Postback.

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    this.BindGrid();
  }
}

Now generate ExporttoPdf button click event and code for Generate Password Protected Pdf file.

protected void ExportToPDF(object sender, EventArgs e)
{
  using (StringWriter sw = new StringWriter())
  {
    using (HtmlTextWriter hw = new HtmlTextWriter(sw))
    {
      //To Export all pages
      GridView1.AllowPaging = false;
      this.BindGrid();

      GridView1.RenderControl(hw);
      StringReader sr = new StringReader(sw.ToString());
      Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
      HTMLWorker htmlparser = new HTMLWorker(pdfDoc);
      using (MemoryStream memoryStream = new MemoryStream())
      {
        PdfWriter.GetInstance(pdfDoc, memoryStream);
        pdfDoc.Open();
        htmlparser.Parse(sr);
        pdfDoc.Close();
        byte[] bytes = memoryStream.ToArray();
        memoryStream.Close();
        using (MemoryStream input = new MemoryStream(bytes))
        {
          using (MemoryStream output = new MemoryStream())
          {
            string password = "Umesh";
            PdfReader reader = new PdfReader(input);
            PdfEncryptor.Encrypt(reader, output, true, password, password, PdfWriter.ALLOW_SCREENREADERS);
            bytes = output.ToArray();
            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition", "attachment;filename=" + "Export_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToString("T") + ".pdf");
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.BinaryWrite(bytes);
            Response.End();
          }
        }
      }
    }
  }
}

Here I have Set Password “Umesh” and Name it When Pdf file Export like "Export_Todate.Pdf". When you Run and Export file from Gridview you can see in your Downloaded file.

Now Click on Export to Pdf button and Download Pdf File and Open Pdf file.

Now Enter Password and see Data from that Pdf File.
Export datagridview to pdf in windows form application in asp.net

Export datagridview to pdf in windows form application in asp.net

Description:-

In this example we explain that how to export DataGridView data to PDF file in Windows Forms (WinForms) Applications using ItextSharp PDF conversion library using C#. DataGridView cannot provide facility to export Griddata directally to pdf and so that we have to use one .dll file and give reference to your project and use the functionality export to pdf in table format by using the iTextSharp.dll Table for this solution.

To export DataGrid data or row to pdf format first download the iTextSharp.dll and the use it in your project. Here below is code to export DataGridView data to pdf with table format and Company logo or image logo with header footer in pdf writing data.

Create Table:-

CREATETABLE [dbo].[cardetail](
 [carno] [nvarchar](50)NOTNULL,
 [carname] [nvarchar](50)NOTNULL,
 [address] [nvarchar](50)NOTNULL,
 [personname] [varchar](50)NOTNULL,
 [cellno] [bigint] NOTNULL,
 [detail] [nvarchar](50)NOTNULL,
 [total] [bigint] NOTNULL,
 [id] [bigint] IDENTITY(1,1)NOTNULL,
CONSTRAINT [PK_cardetail] PRIMARYKEYCLUSTERED
(
 [id] ASC
)WITH (PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)ON [PRIMARY]
)ON [PRIMARY]

GO

Default.aspx.cs:-

SqlConnection cn = new SqlConnection("ConnectionString");
Int32 empid;
public Form1()
{
  //this.cardetail_Load();
  InitializeComponent();
}

//function for pass data to this function as a datareader and its display in pdf table format 
private void GenerateBillAndExport(SqlDataReader Reader)
{
if (Reader.HasRows)
{
  if (Reader.Read())
  {
    PdfPTablePdfPTable = newPdfPTable(4);
    PdfPTable.DefaultCell.Padding = 3;
    PdfPTable.WidthPercentage = 100;
    PdfPTable.HorizontalAlignment = Element.ALIGN_LEFT;
    PdfPTable.DefaultCell.BorderWidth = 1;

    PdfPTable.AddCell(new PdfPCell(iTextSharp.text.Image.GetInstance("D://Logo.jpg")) { Border = 0 });
    PdfPTable.AddCell(new PdfPCell(new Phrase("Name: " + Reader[3].ToString())) { Border = 0 });
    PdfPTable.AddCell(new PdfPCell(new Phrase("Date :" + DateTime.Now.ToShortDateString())) { Border = 0 });
    PdfPTable.AddCell(new PdfPCell(new Phrase("Mobile No  :" + Reader[4].ToString())) { Border = 0 });

    PdfPTable.AddCell(new PdfPCell(new Phrase("CarName")) { BackgroundColor = iTextSharp.text.BaseColor.GRAY });
    PdfPTable.AddCell(new PdfPCell(new Phrase("Detail")) { BackgroundColor = iTextSharp.text.BaseColor.GRAY });
    PdfPTable.AddCell(new PdfPCell(new Phrase("Total")) { BackgroundColor = iTextSharp.text.BaseColor.GRAY });
    PdfPTable.AddCell(new PdfPCell(new Phrase("CarNo")) { BackgroundColor = iTextSharp.text.BaseColor.GRAY });

    PdfPTable.AddCell(Reader[1].ToString());
    PdfPTable.AddCell(Reader[5].ToString());
    PdfPTable.AddCell(Reader[6].ToString());
    PdfPTable.AddCell(Reader[0].ToString());
    //add blank row 
    iTextSharp.text.pdf.PdfPCell c1 = new iTextSharp.text.pdf.PdfPCell(new Phrase(" "));
    iTextSharp.text.pdf.PdfPCell c2 = new iTextSharp.text.pdf.PdfPCell(new Phrase(" "));
    iTextSharp.text.pdf.PdfPCell c3 = new iTextSharp.text.pdf.PdfPCell(new Phrase(" "));
    iTextSharp.text.pdf.PdfPCell c4 = new iTextSharp.text.pdf.PdfPCell(new Phrase(" "));
    PdfPTable.AddCell(c1);
    PdfPTable.AddCell(c2);
    PdfPTable.AddCell(c3);
    PdfPTable.AddCell(c4);
    //Add Footer row 
    PdfPTable.AddCell(newPdfPCell(new Phrase("Name:- Umesh Adroja" + Environment.NewLine + "Contact No:- 8000762096"))
    {
      BackgroundColor = iTextSharp.text.BaseColor.LIGHT_GRAY
    });
    PdfPTable.AddCell(newPdfPCell(new Phrase("")));
    PdfPTable.AddCell(newPdfPCell(new Phrase("")));
    PdfPTable.AddCell(newPdfPCell(new Phrase("")));
    //PdfPTable.AddCell(new PdfPCell(new Phrase("Name:- Umesh Adroja" + Environment.NewLine + "Contact No:- 8000762096"))
    //{
    //    BackgroundColor = iTextSharp.text.BaseColor.LIGHT_GRAY
    //});
    //Exporting to PDF 
    stringfolderPath = "D:\\PDFs\\";
    if (!Directory.Exists(folderPath))
    {
      Directory.CreateDirectory(folderPath);
    }
    //Reader.GetValue(0) + "_" + DateTime.Now.ToShortDateString() 
    FileStream stream = new FileStream(folderPath + Reader.GetValue(0) + "_" + ".pdf", FileMode.Create);
    using (stream)
    {
      Document pdfDoc = new Document(PageSize.A2, 10f, 10f, 10f, 0f);
      PdfWriter.GetInstance(pdfDoc, stream);
      pdfDoc.Open();
      pdfDoc.Add(PdfPTable);
      pdfDoc.Close();
      stream.Close();
      System.Diagnostics.Process.Start(folderPath + Reader.GetValue(0) + "_" + ".pdf");
    }
  }
}
}

private void cardetail_Load(object sender, EventArgs e)
{
  DataTable dt = binddata();
  dataGridView2.DataSource = dt;
  dataGridView2.AutoGenerateColumns = false;
  dataGridView2.AllowUserToAddRows = false;
  DataGridViewLinkColumnEditlink = newDataGridViewLinkColumn();
  Editlink.UseColumnTextForLinkValue = true;
  Editlink.HeaderText = "Edit";
  Editlink.DataPropertyName = "lnkColumn";
  Editlink.LinkBehavior = LinkBehavior.SystemDefault;
  Editlink.Text = "Edit";
  dataGridView2.Columns.Add(Editlink);
  DataGridViewLinkColumnDeletelink = newDataGridViewLinkColumn();
  Deletelink.UseColumnTextForLinkValue = true;
  Deletelink.HeaderText = "delete";
  Deletelink.DataPropertyName = "lnkColumn";
  Deletelink.LinkBehavior = LinkBehavior.SystemDefault;
  Deletelink.Text = "Delete";
  dataGridView2.Columns.Add(Deletelink);
  DataGridViewLinkColumnPrintlink = newDataGridViewLinkColumn();
  Printlink.UseColumnTextForLinkValue = true;
  Deletelink.HeaderText = "Export to pdf";
  Printlink.DataPropertyName = "lnkColumn";
  Printlink.LinkBehavior = LinkBehavior.SystemDefault;
  Printlink.Text = "Export to pdf";
  dataGridView2.Columns.Add(Printlink);
}

//Binding Gridview <!--[if !supportLineBreakNewLine]--><!--[endif]-->
public DataTable binddata()
{
  DataTable dt = new DataTable();
  string query = "select * from cardetail";
  SqlCommand cmd = new SqlCommand(query, cn);
  SqlDataAdaptersa = new SqlDataAdapter();
  sa.SelectCommand = cmd;
  cn.Open();
  cmd.ExecuteNonQuery();
  sa.Fill(dt);
  dataGridView2.DataSource = dt;
  dataGridView2.AutoGenerateColumns = false;
  dataGridView2.AllowUserToAddRows = false;
  cn.Close();
  returndt;
}

//Edit Delete Event <!--[if !supportLineBreakNewLine]--><!--[endif]-->
private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
  SqlCommand cmd;
  SqlCommand Command;
  SqlDataReader Reader;
  try
  {
    empid = Convert.ToInt32(dataGridView2.Rows[e.RowIndex].Cells["id"].Value);
    switch (e.ColumnIndex)
    {
      case 0:
        cn.Open();
        Command = new SqlCommand("Select * from cardetail where id='" + empid + "'", cn);
        Reader = Command.ExecuteReader();
        if (Reader.HasRows)
        {
          if (Reader.Read())
          {
            textBox8.Text = Reader.GetValue(0).ToString();
            textBox9.Text = Reader.GetValue(1).ToString();
            textBox10.Text = Reader.GetValue(2).ToString();
            textBox11.Text = Reader.GetValue(3).ToString();
            textBox12.Text = Reader.GetValue(4).ToString();
            textBox13.Text = Reader.GetValue(5).ToString();
            textBox14.Text = Reader.GetValue(6).ToString();

            button4.Visible = true;
            button3.Visible = false;
          }
        }
        cn.Close();
      break;
      case 1:
        cn.Open();
        cmd = new SqlCommand("delete from cardetail where id = '" + empid + "'", cn);
        cmd.ExecuteNonQuery();
        cn.Close();
        MessageBox.Show("Deleted Successfully.....");
        binddata();
      break;
      case 2:
        cn.Open();
        Command = new SqlCommand("Select * from cardetail where id='" + empid + "'", cn);
        Reader = Command.ExecuteReader();
        GenerateBillAndExport(Reader);
        cn.Close();
      break;
    }
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
}

//Update Button Click <!--[if !supportLineBreakNewLine]--><!--[endif]-->
private void button4_Click(object sender, EventArgs e)
{
  string a = DateTime.Now.ToShortDateString();
  string query = "update cardetail set carno='" + textBox8.Text + "',carname='" + textBox9.Text + "',address='" + textBox10.Text + "',personname='" + textBox11.Text + "',cellno='" + textBox12.Text + "',detail='" + textBox13.Text + "',total='" +   Convert.ToDouble(textBox14.Text) + "' where id='" + empid + "'";
  SqlCommand cmd = new SqlCommand(query, cn);
  cn.Open();
  cmd.ExecuteNonQuery();
  MessageBox.Show("Record Updates Successfully.....");
  cn.Close();
  //clear();
  binddata();
  button3.Visible = true;
  button4.Visible = false;
}

private void Form1_Load(object sender, EventArgs e)
{
  // TODO: This line of code loads data into the 'uHDataSet1.cardetail' table. You can move, or remove it, as needed.
  this.cardetailTableAdapter1.Fill(this.uHDataSet1.cardetail);
  // TODO: This line of code loads data into the 'uHDataSet.cardetail' table. You can move, or remove it, as needed.
  // this.cardetailTableAdapter.Fill(this.uHDataSet.cardetail);
  this.binddata();
}

//Insert button Code
private void button3_Click(object sender, EventArgs e)
{
  string a = DateTime.Now.ToShortDateString();
  string query = "insert into cardetail values(@carno,@carname,@address,@personname,@cellno,@detail,@total)";
  SqlCommand cmd = new SqlCommand(query, cn);
  cmd.Parameters.AddWithValue("@carno", textBox8.Text);
  cmd.Parameters.AddWithValue("@carname", textBox9.Text);
  cmd.Parameters.AddWithValue("@address", textBox10.Text);
  cmd.Parameters.AddWithValue("@personname", textBox11.Text);
  cmd.Parameters.AddWithValue("@cellno", textBox12.Text);
  cmd.Parameters.AddWithValue("@detail", textBox13.Text);
  cmd.Parameters.AddWithValue("@total", textBox14.Text);
  cn.Open();
  cmd.ExecuteNonQuery();
  MessageBox.Show("Record Inserted Successfully.....");
  cn.Close();
  //clear();
  binddata();
  button3.Visible = false;
  button4.Visible = true;
}

iTextSharp - Page Layout with Columns in Asp.Net

Description:-

Most often, when working with columns you will want to add multiple columns for text layout, similar to a newspaper. ITextSharp has a MultiColumnText object which makes this pretty simple. All you need to tell it is where the leftmost column should start from along the X-axis, where that rightmost column should end, what space you would like between the columns and how many columns you want. The following adds 2 columns to a page, and then adds a paragraph 8 times:  

string pdfpath = Server.MapPath("PDFs");
string imagepath = Server.MapPath("Columns");
Document doc = newDocument();
try
{
  PdfWriter.GetInstance(doc, newFileStream(pdfpath + "/Columns.pdf", FileMode.Create));
  doc.Open();
  Paragraph heading = newParagraph("Page Heading", newFont(Font.HELVETICA, 28f, Font.BOLD));
  heading.SpacingAfter = 18f;
  doc.Add(heading);
  string text = @"Loremipsum dolor sit amet, consectetueradipiscingelit. Suspendisseblanditblanditturpis.Nam in lectusut dolor consectetuerbibendum.Morbinequeipsum, laoreet id; dignissimet, viverra id, mauris. Nullamauriselit, consectetuer sit amet, accumsaneget, congue ac, libero. Vivamussuscipit.Nuncdignissimconsectetuerlectus.Fusceelit nisi; commodonon, facilisisquis, hendreriteu, dolor? Suspendisseeleifend nisi ut magna.Phasellus id lectus! Vivamuslaoreetenimet dolor. Integer arcumauris, ultriciesvel, portaquis, venenatis at, libero.Donecnibhest, adipiscing et, ullamcorper vitae, placerat at, diam. Integer ac turpisvel ligula rutrumauctor! Morbiegestaserat sit amet diam. Ututipsum? Aliquam non sem. Nullarisuseros, mollisquis, blanditut; luctuseget, urna.Vestibulumvestibulumdapibuserat.Proinegestasleo a metus?";
  MultiColumnText columns = newMultiColumnText();

  //float left, float right, float gutterwidth, int numcolumns
  columns.AddRegularColumns(36f, doc.PageSize.Width - 36f, 24f, 2);
 
  Paragraphpara = newParagraph(text, newFont(Font.HELVETICA, 8f));
  para.SpacingAfter = 9f;
  para.Alignment = Element.ALIGN_JUSTIFIED;
  for (int i = 0; i < 8; i++)
  {
    columns.AddElement(para);
  }
 
  doc.Add(columns);
}
catch (Exception ex)
{
  //Log(ex.Message);
}
finally
{
  doc.Close();
}  

The result shows how the text just flowed from one column to another once the first column was filled.

AddRegularColumns() will set each column at exactly the same width. AddSimpleColumn() allows you to specify the width of individual columns, which means that you can work with irregularly sized columns:  

columns.AddSimpleColumn(36f, 170f);
columns.AddSimpleColumn(194f, doc.PageSize.Width - 36f);  

The code above replaces the AddRegularColumn() call in the preceding block and creates two separate column objects. The first starts at the left margin (36 points in from the left edge) and is 2 inches wide (170 - 36 = 144 points). The second column starts 24 points (1/3 of an inch) further over and butts up against the right hand margin.


Adding other elements such as images and tables is straightforward: 

string pdfpath = Server.MapPath("PDFs");
string pdfpath = Server.MapPath("PDFs");
string imagepath = Server.MapPath("Images");
Document doc = new Document();
try
{
  PdfWriter.GetInstance(doc, new FileStream(pdfpath + "/Columns1.pdf", FileMode.Create));
  doc.Open();
  Paragraph heading = new Paragraph("Page Heading", newFont(Font.HELVETICA, 28f, Font.BOLD));
  heading.SpacingAfter = 18f;
  doc.Add(heading);
  string text = @"Loremipsum dolor sit amet, consectetueradipiscingelit. Suspendisseblanditblanditturpis.Nam in lectusut dolor consectetuerbibendum.Morbinequeipsum, laoreet id; dignissimet, viverra id, mauris. Nullamauriselit, consectetuer sit amet, accumsaneget, congue ac, libero. Vivamussuscipit.Nuncdignissimconsectetuerlectus.Fusceelit nisi; commodonon, facilisisquis, hendreriteu, dolor? Suspendisseeleifend nisi ut magna.Phasellus id lectus! Vivamuslaoreetenimet dolor. Integer arcumauris, ultriciesvel, portaquis, venenatis at, libero.Donecnibhest, adipiscing et, ullamcorper vitae, placerat at, diam. Integer ac turpisvel ligula rutrumauctor! Morbiegestaserat sit amet diam. Ututipsum? Aliquam non sem. Nullarisuseros, mollisquis, blanditut; luctuseget, urna.Vestibulumvestibulumdapibuserat.Proinegestasleo a metus?";
  MultiColumnText columns = new MultiColumnText();
  columns.AddSimpleColumn(36f, 336f);
  columns.AddSimpleColumn(360f, doc.PageSize.Width - 36f);

  Paragraphpara = new Paragraph(text, new Font(Font.HELVETICA, 8f));
  para.SpacingAfter = 9f;
  para.Alignment = Element.ALIGN_JUSTIFIED;

  PdfPTable table = new PdfPTable(3);
  float[] widths = new float[] { 1f, 1f, 1f };
  table.TotalWidth = 300f;
  table.LockedWidth = true;
  table.SetWidths(widths);
  PdfPCell cell = new PdfPCell(newPhrase("Header spanning 3 columns"));
  cell.Colspan = 3;
  cell.HorizontalAlignment = 0;
  table.AddCell(cell);
  table.AddCell("Col 1 Row 1");
  table.AddCell("Col 2 Row 1");
  table.AddCell("Col 3 Row 1");
  table.AddCell("Col 1 Row 2");
  table.AddCell("Col 2 Row 2");
  table.AddCell("Col 3 Row 2");

  iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(imagepath + "/Jellyfish.jpg");
  jpg.ScaleToFit(300f, 300f);
  jpg.SpacingAfter = 12f;
  jpg.SpacingBefore = 12f;

  columns.AddElement(para);
  columns.AddElement(table);
  columns.AddElement(jpg);
  columns.AddElement(para);
  columns.AddElement(para);
  columns.AddElement(para);
  columns.AddElement(para);
  doc.Add(columns);
}
catch (Exception ex)
{
  //Log(ex.Message);
}
finally
{
  doc.Close();
} 

The example above takes a table and images from previous tutorials, and adds them together with the paragraph to the columns. the first column is 300 points wide, and the second one takes up the remainder of the page width.

MultiColumnText is great for creating columns without too much code, but it lacks an element of control. ColumnText provides much more, but requires more code. The following sample shows ColumnText being used to create irregular columns, in that the first one has chunk taken from the top left corner to accommodate an image which is shown here in the resulting PDF:


string pdfpath = Server.MapPath("PDFs");
string imagepath = Server.MapPath("Images");
FontFactory.RegisterDirectory("C:\\WINDOWS\\Fonts");

Document doc = new Document();
Font font1 = new Font(FontFactory.GetFont("adobe garamond pro", 36f, Color.GRAY));
Font font2 = new Font(Font.TIMES_ROMAN, 9f);
doc.SetMargins(45f, 45f, 60f, 60f);
try
{
  FileStream output = new FileStream(pdfpath + "/IrregularColumns.pdf", FileMode.Create);
  PdfWriter writer = PdfWriter.GetInstance(doc, output);
  doc.Open();
  PdfContentBytecb = writer.DirectContent;
  ColumnTextct = new ColumnText(cb);
  ct.Alignment = Element.ALIGN_JUSTIFIED;

  Paragraph heading = new Paragraph("Chapter 1", font1);
  heading.Leading = 40f;
  doc.Add(heading);
  iTextSharp.text.Image L = iTextSharp.text.Image.GetInstance(imagepath + "/ajax-loader(1).gif");
  L.SetAbsolutePosition(doc.Left, doc.Top - 180);
  doc.Add(L);

  ct.AddText(new Phrase("oremipsum dolor sit amet, consectetueradipiscingelit. Suspendisseblanditblanditturpis.Nam in lectusut dolor consectetuerbibendum.Morbinequeipsum, laoreet id; dignissimet, viverra id, mauris. Nullamauriselit, consectetuer sit amet, accumsaneget, congue ac, libero. Vivamussuscipit.Nuncdignissimconsectetuerlectus.Fusceelit nisi; commodonon, facilisisquis, hendreriteu, dolor? Suspendisseeleifend nisi ut magna.Phasellus id lectus! Vivamuslaoreetenimet dolor. Integer arcumauris, ultriciesvel, portaquis, venenatis at, libero.Donecnibhest, adipiscing et, ullamcorper vitae, placerat at, diam. Integer ac turpisvel ligula rutrumauctor! Morbiegestaserat sit amet diam. Ututipsum? Aliquam non sem. Nullarisuseros, mollisquis, blanditut; luctuseget, urna.Vestibulumvestibulumdapibuserat.Proinegestasleo a metus?\n\n", font2));
  
  ct.AddText(new Phrase("Vivamusenim nisi, mollis in, sodalesvel, convallis a, augue? Proin non enim.Nullamelementumeuismoderat.Aliquammalesuadaeleifend quam! Nullafacilisi.Aeneanutturpis ac esttempormalesuada. Maecenas scelerisqueorci sit ametauguelaoreet tempus. Duisinterdumestuteros. Fusce dictum dignissimelit.Morbi at dolor.Fusce magna.Nullatellusturpis, mattisut, eleifend a, adipiscing vitae, mauris.Pellentesquemattislobortis mi.\n\n", font2));

  ct.AddText(new Phrase("Nullam sit ametmetusscelerisquediamhendreritporttitor. Aeneanpellentesque, lorem a consectetuerconsectetuer, nuncmetushendrerit quam, mattisultricesloremtelluslaciniamassa. Aliquam sit ametodio. Proinmauris.Integer dictum quam a quam accumsanlacinia.Pellentesquepulvinarfeugiateros.Suspendisserhoncus.Sedconsectetuerleoeu nisi. Suspendissemassa! Sedsuscipit lacus sit ametelit! Aliquamsollicitudincondimentumturpis.Nuncutaugue! Maecenas eueros.Morbi in urnaconsectetueripsumvehiculatristique.\n\n", font2));
  
  ct.AddText(new Phrase("Donecimperdietpurusvel ligula. Vestibulumtempor, odioutscelerisqueeleifend, nullasapienlaoreet dui; velaliquamarculiberoeu ante.Curabiturrutrumtristique mi. Sedlobortisiaculisarcu.Suspendissemauris.Aliquammetus lacus, elementumquis, mollis non, consequatnec, tortor.\n", font2));

  ct.AddText(new Phrase("Quisque id diam. Utegestasleo a elit. Nulla in metus.Aliquamiaculisturpis non augue.Donec a nunc?Phaselluseueros.Nam luctus.Duiseu mi. Utmollis.Nullafacilisi.Loremipsumdolor sitamet, consectetueradipiscingelit. Class aptenttacitisociosquadlitoratorquent per conubia nostra, per inceptoshimenaeos.Aeneanpede.Nullafacilisi.Vestibulummattisadipiscingnulla.Praesentorci ante, mattis in, cursuseget, posueresed, mauris.\n\n", font2));

  ct.AddText(new Phrase("Nullafacilisi. Nuncaccumsanrisusaliquet quam. Nam pellentesque! Aeneanporttitor.Aeneancongueullamcorpervelit.Phasellussuscipitplacerattellus.Vivamusdiamodio, tempus quis, suscipit a, dictum eu; lectus.Sedvelnisl.Utinterdumurnaeunibh.Praesentvehicula, orci id venenatisultrices, maurisurnamollis lacus, etblanditodio magna at enim. Pellentesqueloremfelis, ultricesquis, gravidased, pharetra vitae, quam.Maurisliberoipsum, pharetra a, faucibusaliquet, pellentesque in, mauris.Cras magna neque, interdumvel, variusnec; vulputate at, erat. Quisque vitae urna.Suspendissepotenti.Nullaluctuspurus at turpis! Vestibulum vitae dui.Nullamodio.\n\n", font2));
  
  ct.AddText(new Phrase("Vestibulum ante ipsumprimis in faucibusorciluctus et ultricesposuerecubiliaCurae; Sedeget mi at semiaculishendrerit. Nullafacilisi.Etiamsedelit.In viverradapibussapien.Aliquam nisi justo, ornarenon, ultricies vitae, aliquam sit amet, risus! Cum sociisnatoquepenatibusetmagnis dis parturient montes, nasceturridiculus mus. Phasellusrisus. Vestibulumpretiumaugue non mi. Sed magna.In hachabitasseplateadictumst.Quisquemassa. Etiamviverradiampharetra ante.Phasellusfringillavelitutodio! Nam necnulla.\n\n", font2));

  ct.AddText(new Phrase("Integer augue. Morbiorci.Sedquisnibh.Nullam ac magna id leofaucibusornare. Vestibulumegetlectus sit ametnuncfacilisisbibendum. Donecadipiscingconvallis mi. Cumsociisnatoquepenatibus et magnis dis parturient montes, nasceturridiculus mus. Vivamusenim. Mauris ligula lorem, pellentesquequis, semper sed, tristique sit amet, justo.Suspendissepotenti.Proin vitae enim.Morbi et nisi sit ametsapienve.\n\n", font2));

  float gutter = 15f;
  float colwidth = (doc.Right - doc.Left - gutter) / 2;
  float[] left = { doc.Left + 90f , doc.Top - 80f,
  doc.Left + 90f, doc.Top - 170f,
  doc.Left, doc.Top - 170f,
  doc.Left ,doc.Bottom };

  float[] right = { doc.Left + colwidth, doc.Top - 80f,
  doc.Left + colwidth, doc.Bottom };

  float[] left2 = { doc.Right - colwidth, doc.Top - 80f,
  doc.Right - colwidth, doc.Bottom };

  float[] right2 = {doc.Right, doc.Top - 80f,
  doc.Right, doc.Bottom };

  int status = 0;
  int i = 0;
  //Checks the value of status to determine if there is more text
  //If there is, status is 2, which is the value of NO_MORE_COLUMN
  while (ColumnText.HasMoreText(status))
  {
    if (i == 0)
    {
      //Writing the first column
      ct.SetColumns(left, right);
      i++;
    }
    else
    {
      //write the second column
      ct.SetColumns(left2, right2);
    }
    //Needs to be here to prevent app from hanging
    ct.YLine = doc.Top - 80f;
    //Commit the content of the ColumnText to the document
    //ColumnText.Go() returns NO_MORE_TEXT (1) and/or NO_MORE_COLUMN (2)
    //In other words, it fills the column until it has either run out of column, or text, or both
    status = ct.Go();
  }
}
catch (Exception ex)
{
  //Log(ex.Message);
}
finally
{
  doc.Close();
}

ColumnText requires that you need a PDFContentByte object. This is nearly always the case when you want to place stuff at fixed positions. The code above starts by defining a document object, and then creating some fonts to work with, as well as setting the margins of the document (which needs to be done before the document is opened to take effect). A PdfWriter object is created so that the PDFContentByte object can be instantiated from its DirectContent property. Then a ColumnText object is created using the PDFContentByte. A heading is added, followed by the illustrated capital "L", which starts the Chapter. This is followed by a number of Phrases, set out as paragraphs.

So, now the ColumnText object has its text content, but nowhere to put it yet, so the two columns are created. The first array of floats defines the irregular shape of the left hand side fo the first column which has to the top corner chopped out of it to make way for the image. The second array defines the straight right hand edge. The third and fourth arrays take care of the regularly shaped second column. Two int variables are created to hold the value of the status of the column with regard to whether there is any more text to be added (status), and then the number of the column that is currently being worked on (i).

ColumnText.HasMoreText(status) is a convenience method that takes an int as a parameter. It examines the value of the parameter to see if there is any more text to be added and returns true if there is. The value that returns false is 1. It is initialised at 0 to start, so HasMoreText returns true. Since i is also 0, the code executes to add the first column, then the YLine is set to the top of the column. This must be done, otherwise the application will just spin until the execution timeout occurs. Finally, the ColumnText.Go() method is called. This actually commits the contents of the ColumnText to the document, and also returns a value to the variable status. It returns either NO_MORE_TEXT, which is 1, and/or NO_MORE_COLUMN (2). If NO_MORE_TEXT is returned, everything has been written, otherwise the second column is created and the text added to that. Once ColumnText.HasMoreText returns false, the page is written.

Building on this, if the amount of text spans more than one page, the routine can be rewritten to call Document.NewPage(), and if Go() is called after each Phrase is added to the ColumnText object, it is possible to obtain the current Y position on the page to establish how much room there is left. this enables you to manage widows and orphans - single lines of text that are belong to a paragraph that appear at the end of the preceding page or column (orphans) or appear at the top of a new page or column (widows). It is also possible to pass the parameter "false" into Go(), which does not commit the text to the column, but still allows you to obtain the position as if it was to allow you much finer control over layout.

Itextsharp - Working with images in asp.net

Itextsharp - Working with images in asp.net

Description:-

iTextSharp supports all the main image types: jpg, tif, gif, bmp, png and wmf. There are a number of ways to create images with iTextSharp using the Image.GetInstance() method. Probably the most used option will be to pass a filesystem path and file name into the method: 

string pdfpath = Server.MapPath("PDFs");
string imagepath = Server.MapPath("Images");
Document doc = newDocument();
try
{
  PdfWriter.GetInstance(doc, newFileStream(pdfpath + "/Images.pdf", FileMode.Create));
  doc.Open();
  //New
  doc.Add(newParagraph("GIF"));
  iTextSharp.text.Image gif = iTextSharp.text.Image.GetInstance(imagepath + "/ajax-loader(1).gif");
  doc.Add(gif);
}
catch (Exception ex)
{
  //Log error;
}
finally
{
  doc.Close();
}

Alternative constructors that you may use include passing a URL or a System.Drawing.Image object (as opposed to an iTextSharp.text.Image). Note - the following snippet that System.Drawing.Image.FromStream() method shows the use of namespace aliasing again (sd.Image.FromStream(fs)), as was highlighted to avoid clashes with the two different types of Image object: 

doc.Add(newParagraph("JPG"));
string url = @"D:\Done\AnimationChart\AnimationChart\Images\Jellyfish.jpg";
iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(newUri(url));
jpg.ScaleToFit(250f, 100f);
doc.Add(jpg);
doc.Add(newParagraph("PNG"));
using (FileStreamfs = new FileStream(imagepath + "/vuserpic_1.png", FileMode.Open))
{
  iTextSharp.text.Imagepng = iTextSharp.text.Image.GetInstance(System.Drawing.Image.FromStream(fs), ImageFormat.Png);
  doc.Add(png);
}

It's difficult to tell from the images I have provided so far, but the resolution of the resulting images in the PDF file is not that great. By default, images are embedded at 72 dpi (Dots Per Inch) which coincidentally, matches the number of points in an inch. If this file was being prepared for printing, the final job would be a bit nasty. Generally, commercial printers require that colour images for printing have a resolution of 300 dpi. To achieve this, you can scale the image to 24%. What you are actually trying to do is squeeze 300 pixels into the space that 72 normally occupies. 72/300 * 100 = 24%. The image stays the same in terms of file size but occupies less space in the document. 

doc.Add(newParagraph("TIF Scaled to 300dpi"));
iTextSharp.text.Imagetif = iTextSharp.text.Image.GetInstance(imagepath + "/WelcomeFax.tif");
tif.ScalePercent(24f);
doc.Add(tif);

Now, I have a large tif file that I want to use as a logo on an A4 letterhead. It measures 300 x 890 pixels. So at the default 72 dpi, it will measure 4.17 inches wide by12.36 inches deep. Increasing the resolution to 300 dpi will reduce the width to 1 inch, and the depth to 2.97 inches (72 points by 213.6 points). That part is fine. We can do that using the code above. Now I want to place the 300 dpi image in a particular position on the page. I have in mind the top right hand corner. The SetAbsolutePosition() method will do this, but I need to get a calculator out.

SetAbsolutePosition() accepts 2 floats as parameters. The first represents the co-ordinate along the X-axis, which starts at the left hand edge of the document and finishes at the right hand edge of the document. The second represents the Y-axis co-ordinate which starts from the bottom of the document and goes to the top. An A4 document is 595 points wide and 842 pixels high with a 36 point margin all around by default.

The actual co-ordinate that needs to be passed in is the bottom left of the image position. This image will butt right up to the right-hand margin. The image is 72 points wide (1 inch) + the margin at 36 points (total 108 points) from the right hand edge of the document, or 595 - 108 = 487 points along the X-axis. The Y-axis co-ordinate is the height of the image + the margin away from the top of the document, or 842 - (213.6 + 36) = 592.4 points from the bottom. Cripes. I don't really want to have to remember all the various sizes of different documents and do these calculations every time I want to set the absolute position of an element. And fortunately, I don't have to. I can use the 
Document.PageSize object to do the work for me.

iTextSharp.text.Image tif1 = iTextSharp.text.Image.GetInstance(imagepath + "/NewFile.tif");
tif1.ScalePercent(24f);
tif1.SetAbsolutePosition(doc.PageSize.Width - 36f - 72f,
doc.PageSize.Height - 36f - 216.6f);
doc.Add(tif1);

doc.PageSize.Width gives me the width in points of the document, and I just remove the margin (36 points) and the width of the image (72 points) for the X-axis co-ordinate, and the margin and height of the image from the total height of the document for the Y-axis co-ordinate.
Another scenario that might need to be catered for is to fit a user-supplied image into a fixed size box somewhere on a form. I've pinched the Sunset image that I found in the Sample Images folder in My Pictures that comes as part of the default install of WindowsXP to illustrate how to use the ScaleToFit() method to achieve this. The following code takes an image of 800 x 600 and forces it to resize, maintaining its aspect ratio, into a rectangle measuring 250 points square.

iTextSharp.text.Image jpg1 = iTextSharp.text.Image.GetInstance(imagepath + "/Desert.jpg");
jpg1.ScaleToFit(250f, 250f);
jpg1.Border = Rectangle.BOX;
jpg1.BorderColor = Color.YELLOW;
jpg1.BorderWidth = 5f;
doc.Add(jpg1);
doc.Add(new Paragraph("Original Width: " + jpg1.Width.ToString()));
doc.Add(new Paragraph("Original Height " + jpg1.Height.ToString()));
doc.Add(new Paragraph("Scaled Width: " + jpg1.ScaledWidth.ToString()));
doc.Add(new Paragraph("Scaled Height " + jpg1.ScaledHeight.ToString()));
float Resolution = jpg1.Width / jpg1.ScaledWidth * 72f;
doc.Add(new Paragraph("Resolution: " + Resolution)); 

I have also taken the opportunity to add a yellow border to the embedded image, which is 5 points wide, and then shown the original dimensions, followed by the scaled dimensions, and the resulting resolution of the image.

If you use SetAbsolutePosition() you end up with the same effect as if you had set the Alignment property of the image to Image.UNDERLYING, in that text added to the document will run over the top of it. Unless you want to achieve this kind of watermark effect, you need to use Image.TEXTWRAP instead. 

iTextSharp.text.Image jpg2 = iTextSharp.text.Image.GetInstance(imagepath + "/Desert.jpg");
Paragraphparagraph = newParagraph(@"Loremipsum dolor sit amet, consectetueradipiscingelit. Suspendisseblanditblanditturpis.Nam in lectusut dolor consectetuerbibendum.Morbinequeipsum, laoreet id; dignissimet, viverra id, mauris. Nullamauriselit, consectetuer sit amet, accumsaneget, congue ac, libero. Vivamussuscipit.Nuncdignissimconsectetuerlectus.Fusceelit nisi; commodonon, facilisisquis, hendreriteu, dolor? Suspendisseeleifend nisi ut magna.Phasellus id lectus! Vivamuslaoreetenimet dolor. Integer arcumauris, ultriciesvel, portaquis, venenatis at, libero.Donecnibhest, adipiscing et, ullamcorper vitae, placerat at, diam. Integer ac turpisvel ligula rutrumauctor! Morbiegestaserat sit amet diam. Ututipsum? Aliquam non sem. Nullarisuseros, mollisquis, blanditut; luctuseget, urna.Vestibulumvestibulumdapibuserat.Proinegestasleo a metus?");
paragraph.Alignment = Element.ALIGN_JUSTIFIED;
jpg2.ScaleToFit(250f, 250f);
jpg2.Alignment = iTextSharp.text.Image.TEXTWRAP | iTextSharp.text.Image.ALIGN_RIGHT;
jpg2.IndentationLeft = 9f;
jpg2.SpacingAfter = 9f;
jpg2.BorderWidthTop = 36f;
jpg2.BorderColorTop = Color.WHITE;
doc.Add(jpg2);
doc.Add(paragraph);

In this instance, I added a white border to the image to align it with the top of the text, and a bit of padding to the left and bottom of the image to stop the text running right up to its edge. Left and Right padding can be added using the IndentationLeft and IndentationRight properties, while SpacingBefore and SpacingAfter is used to pad the top and bottom. You may ask why I didn't use SapcingBefore instead of adding a white border, and that's a good question. The fact is that whatever I set the value to for SpacingBefore, it seemed to have no effect whatsover in this instance. I have no idea why this should be, but if anyone does, I'll be pleased to hear from them.

One final thing with images - you can rotate them if you need to. One way to do this is to set the Rotation property, which takes a float. The float value represents an angle measured in Radians. If you did more Mathematics than I did at school, you may be comfortable with this, but if you are like me and ask "What??". you can either work out that a quarter turn (90°) is Pi / 2, or simply set the RotationDegrees property instead. Rotation by default is anti-clockwise. The following are equally valid and equivalent: 

jpg2.Rotation = (float)Math.PI / 2;
jpg2.RotationDegrees = 90f;

iTextSharp - Drawing shapes and Graphics in Asp.Net


Description:-


Up till now, all content added to the PDF documents in previous articles have relied on Simple iText, which takes care of positioning content within the flow of a document. It also looks after creating new pages to accept overflow text etc. Working with graphics needs a slightly different approach, in that we now need to use a PdfContentByte() object explicitly. This is obtained from the PdfWriter object's DirectContent. This also means that instead of just invoking the GetInstance method of the PdfWriter, we actually need to instantiate a PdfWriter object. 

string pdfpath = Server.MapPath("PDFs");
Document doc = new Document();
try
{
  PdfWriter writer = PdfWriter.GetInstance(doc, newFileStream(pdfpath + "/Graphics.pdf", FileMode.Create));
  doc.Open();
  PdfContentByte cb = writer.DirectContent; 
  //Now that we have a working PdfContentByte object, we can use it to start drawing: 
  cb.MoveTo(doc.PageSize.Width / 2, doc.PageSize.Height / 2);
  cb.LineTo(doc.PageSize.Width / 2, doc.PageSize.Height);
  cb.Stroke();
  cb.MoveTo(0, doc.PageSize.Height / 2);
  cb.LineTo(doc.PageSize.Width, doc.PageSize.Height / 2);
  cb.Stroke();
}
catch (Exception ex)
{
  //Log error;
}
finally
{
  doc.Close();
} 

The first line moves to the x, y coordinates specified in the parameters passed in, which in this case is halfway across the document, and halfway up (or the center point). The next line draws a line from this point to the position specified in the LineTo() method, which is still halfway across the document, but at the top of it. Actually, it doesn't "draw" it, but really only describes our intention. The line is only actually committed to the document when Stroke() is called. The second line is drawn from the lefthand edge, at a position halfway up the document to the righthand edge at the same height - so we end up with the top two quarters of the document outlined.

Using the same methodology, we can add a square to the top left quarter: 

cb.MoveTo(100f, 700f);
cb.LineTo(200f, 700f);
cb.LineTo(200f, 600f);
cb.LineTo(100f, 600f);
cb.ClosePath();
cb.Stroke(); 

We didn't need to explicitly specify the coordinates for the final side of the square. ClosePath() automatically provides a line from the current position that we are at to the original coordinates. However, there is a quicker way of delivering a square (or rectangle) using one of the convenience shapes provided by iTextSharp. The next bit shows that is action, placing a square in the top right quarter of the document: 

cb.Rectangle(doc.PageSize.Width - 200f, 600f, 100f, 100f);
cb.Stroke();

Four more squares are added to the page, each one illustrating the results of different methods other than Stroke(), used to consign them to the document. But first, the Stroke colour and the Fill colour are set. If you have worked with any graphics packages, such as PhotoShop or FireWorks, you will probably know that Stroke is the outline of an object, and Fill represents its internals bounded by the Stroke. I have used CMYK as the colour space, setting the Stroke colour to Cyan and the Fill colour to Yellow: 

cb.SetColorStroke(newCMYKColor(1f, 0f, 0f, 0f));
cb.SetColorFill(newCMYKColor(0f, 0f, 1f, 0f));

cb.MoveTo(70, 200);
cb.LineTo(170, 200);
cb.LineTo(170, 300);
cb.LineTo(70, 300);
//Path closed and stroked
cb.ClosePathStroke();
cb.Stroke();

cb.MoveTo(190, 200);
cb.LineTo(290, 200);
cb.LineTo(290, 300);
cb.LineTo(190, 300);
//Filled, but not stroked or closed
cb.Fill();
cb.Stroke();

cb.MoveTo(310, 200);
cb.LineTo(410, 200);
cb.LineTo(410, 300);
cb.LineTo(310, 300);
//Filled, stroked, but path not closed
cb.FillStroke();
cb.Stroke();

cb.MoveTo(430, 200);
cb.LineTo(530, 200);
cb.LineTo(530, 300);
cb.LineTo(430, 300);
//Path closed, stroked and filled
cb.ClosePathFillStroke();
cb.Stroke(); 

When using a Rectangle object to represent a square or rectangle instead of drawing it, the first two parameters represent the x and y coordinates of the bottom right hand corner. The final two parameters are the width and height. Other preset shapes include the Circle, but the x and y coordinates that are passed in represent the center point of the shape, followed by a value representing the radius. Looking at the first of the 4 squares above, it is relatively easy to determine that the width and height is 100 points, and that the center point is at 120 x, 250 y. To add a circle to the square so that it fits nicely, the following code will do:

cb.SetCMYKColorStroke(255, 255, 0, 0);
cb.SetCMYKColorFill(0, 255, 255, 0);
cb.SetLineWidth(2f);
cb.Circle(120f, 250f, 50f);
cb.Fill();
cb.Stroke(); 

Rather irritatingly, I found you have to guess at the actual values required by the two methods concerning the use of CMYK colour I have used so far. Neither was intuitive, given that generally, CMYK colours are represented as a series of percentages. For example, Warm Red is referenced as C: 0%, M: 100%, Y: 100%, K: 100%. The constructor for CMYKColor() requires four floats. Providing values that represent the percentages works fine. But I have provided values of 1f and 0f. In fact, I can provide any value I want, so long as it is a valid float. The values are treated as being relative to eachother, so for 100% blue (Cyan) i could just have validly provided 3000f, 0f, 0f, 0f. Strange, but workable if you stick to the usual CMYK percentages, and don't accidentally type in an extra zero.

The SetCMYKColorFill() method used just above accepts ints, rather than floats. I thought maybe this method was working on percentages as I would expect with CMYK, so I originally supplied the value 0, 100, 100, 0 to represent Warm Red. All I got was a washy pinky colour. I thought perhaps there was a bug in there somewhere, and that something was being affected by the previous setting of the Fill colour, so I deployed the ResetCMYKColorFill() method in the hope that it did something. Nope. All it did was reset to the default colour of black. Eventually, I found out CMYKColor is built on the ExtendedColor class, and can accept ints up to 255 - which is reminiscent of the RGB colour values and really confusing unless you know. I applied the values you see above, and got my desired result. To build on the oddity of this approach, I also discovered that there is nothing to prevent you entering values above 255. If you do, it seems that iTextSharp subtracts 255 from whatever you supply, so 256 is the equivalent of 1, and 510 is the equivalent of 255 - or at least, that's the results I got when I tried it.
Anyway, enough of the digression. Here's my red circle with a mauve border (2 points in width) in the first square:

Moving on, here's an example of using another preset shape, the ellipse. First, a rectangle is drawn, then an ellipse is added to fit neatly within it to illustrate how the positioning works through the parameters supplied to the constructor:

// x, y of bottom left corner, width, height
cb.Rectangle(100f, 200f, 300f, 100f);
cb.Stroke();
//Bottom left and top right coordinates
cb.Ellipse(100f, 200f, 400f, 300f);
cb.Stroke(); 

If the differences between the first and third parameter, and the second and fourth parameter are the same, you end up with a circle.
The next example shows another preset shape, the rounded rectangle. When one of these are drawn, the values passed in are the x and y coordinates for the bottom left hand corner, followed by the width and height, and finally the radius of the rounded corners. I have also added a circle in the corner with the same radius as the corner itself to show how the radius of the corner works. I've placed a cross at the center of the circle: 

//Bottom left coordinates followed by width, height and radius of corners
cb.RoundRectangle(100f, 500f, 200f, 200f, 20f);
cb.Stroke();

cb.Circle(120f, 520f, 20f);
cb.Stroke();

cb.MoveTo(118f, 520f);
cb.LineTo(122f, 520f);
cb.Stroke();
cb.MoveTo(120f, 518f);
cb.LineTo(120f, 522f);
cb.Stroke();

Triangles are relatively simple to do, just by drawing the three lines they require. Here's an example of a right-angled triangle with the right angle shown: 

cb.MoveTo(350f, 450f);
cb.LineTo(350f, 600f);
cb.LineTo(500f, 450f);
cb.ClosePathStroke();

cb.MoveTo(350f, 460f);
cb.LineTo(360f, 460f);
cb.LineTo(360f, 450f);
cb.Stroke(); 

Curves and Arcs

Bezier curves are important in Vector Graphics, where they are based on mathematical equations rather than each individual point being specified along the path of the curve. They work by specifying a start point, an end point, and two control points. The first control point is specified in reference to the start point, and the second one is related to the end point. The curve will begin at the start point, and head towards the end point in the direction of the 1st control point. How far it gets near the control point will depend on the distance between the start point and its control point, and the end point and its control point, and the distance between the start and end point themselves. The control points are used for directional purposes, and are rarely hit by the path. If you have ever used a Vector graphics package, like Photoshop or Fireworks, you will have seen these control points, usually with little "handles" on the end of them which you can move to bend the curve.
Here's an example of a curve, that starts at (200, 10), and ends at (350, 150).

//Start Point
cb.MoveTo(200f, 10f);
//Control Point 1, Control Point 2, End Point
cb.CurveTo(150f, 30f, 450f, 70f, 350f, 150f);
cb.Stroke(); 

The curve heads towards the first control point at (150, 30), then bends away towards the second control point at (450, 70), before arriving at the end point. It looks like this:

I'm not really sure that shows a lot, so I will add in some "handles" that show the control points:

cb.MoveTo(200f, 10f);
cb.LineTo(150f, 30f);
cb.Stroke();

cb.MoveTo(450f, 70f);
cb.LineTo(350f, 150f);
cb.Stroke();

cb.Circle(450f, 70f, 1f);
cb.Stroke();
cb.Circle(150f, 30f, 1f);
cb.Stroke(); 

The first control point has a relatively short handle, so the curve only begins to move towards it. The second control point has a longer handle, and this starts to exert its influence on the curve along with the ultimate destination at a relatively early point in its journey, which is reflected in the way the line is "pulled" towards it. This effect is probably best illustrated by changing the second control point so that it is further away, and the angle is altered: 

cb.SetColorStroke(Color.GREEN);
cb.SetColorStroke(Color.GREEN);
//start point (x,y)
cb.MoveTo(200f, 10f);
//control point 1 (x,y), control point 2 (x,y), end point (x,y)
cb.CurveTo(150f, 30f, 550f, 100f, 350f, 150f);
cb.Stroke();

cb.MoveTo(550f, 100f);
cb.LineTo(350f, 150f);
cb.Stroke();

cb.Circle(550f, 100f, 1f);
cb.Stroke();

cb.SetColorStroke(Color.LIGHT_GRAY);

//Bottom Left(x,y), Top Right(x,y), Start Angle, Extent
cb.Arc(350f, 70f, 550f, 130f, 270f, 90f);
cb.SetLineDash(3f, 3f);
cb.Stroke();

cb.SetLineDash(0f);
cb.MoveTo(550f, 100f);
cb.LineTo(535f, 95f);
cb.Stroke();
cb.MoveTo(550f, 100f);
cb.LineTo(552f, 88f);
cb.Stroke();

The original curve is shown in black, while the new one is shown in green. Now you can see that the increased length of the second "handle" has exerted its influence right from the start point, in that the green line starts just slightly beneath the original black one. Since the new second control point is further away from the end point, and is at a slightly more obtuse angle, the green line moves much further towards the second control point before finishing up at the end point.

There are a couple of other points to note about the code for the second curve. One is the Arc object, which has been used in this instance to create the curved arrow illustrating the movement of the original and new second control points. An Arc is part of an ellipse. In this case, the ellipse will fit into a rectangle that has a bottom left corner at (350, 70) and a top right corner at (550, 130). The default direction that an ellipse is drawn is counter-clockwise. The angle at which the arc is started is 270°, and only 90° of it are drawn. Secondly, the SetLineDash() method is shown for the first time in this series of articles, which allows me to draw the arrow as a dashed line.