Wednesday, June 11, 2008

C# Creating MS Word documents

In this post i will show you how to create a simple word document with the COM library. For this you will need MS Word installed on your computer in order to get it work.

First we need to add a reference to the project: right-click project -> add reference -> COM -> Microsoft Word 12.0 Object Library -> Add

Earlier versions should work also, i have Office 2007 installed so i have the 12.0 library. If you want to create documents which work on Office 97 then get an earlier library.

First we add a reference to the class:

using Microsoft.Office.Interop.Word;

Then in our function we create the document:


{
object fileName = "D:\\helloworld.doc";
object novalue = Missing.Value;

ApplicationClass objWord = new ApplicationClass();
Document objWordDoc = objWord.Documents.Add(ref novalue, ref novalue, ref novalue, ref novalue);
objWordDoc.Activate();

object start = 0;
object end = 0;
Range myRange = objWordDoc.Range(ref start, ref end);

myRange.InsertParagraphBefore();
myRange.InsertBefore("Hello world");
//Add shading
myRange.Shading.BackgroundPatternColor = WdColor.wdColorLightOrange;
myRange.Font.Name = "Arial";
myRange.Font.Size = 18;
myRange.ParagraphFormat.SpaceAfter = 0;

//Next paragraph style, first set the range.
myRange.SetRange(myRange.End, myRange.End);
myRange.InsertParagraphBefore();
myRange.InsertBefore("Hello world2");
myRange.InsertParagraphAfter();
//Remove shading
myRange.Shading.BackgroundPatternColorIndex = WdColorIndex.wdAuto;
myRange.Font.Name = "Arial";
myRange.Font.Size = 14;
myRange.ParagraphFormat.SpaceAfter = 0;

objWordDoc.SaveAs(ref fileName, ref novalue, ref novalue, ref novalue,
ref novalue, ref novalue, ref novalue, ref novalue, ref novalue,
ref novalue, ref novalue, ref novalue, ref novalue, ref novalue,
ref novalue, ref novalue); //Parameters can be different to older Word library's

objWord.Quit(ref novalue, ref novalue, ref novalue);
}


All the functions in word are available in the library but there's a LOT and i mean really a lot!

Here are some links which can come handy:

http://www.c-sharpcorner.com/UploadFile/amrish_deep/WordAutomation05102007223934PM/WordAutomation.aspx?MessageChildID=4167&Delete=true

http://support.microsoft.com/kb/316384


Goodluck creating word documents.

Monday, June 2, 2008

How to call a javascript function in serverside code.

Today i was looking for a way to close the window in an C# webapplication. This can be done by using window.close(); in javascript. But how to call this from serverside code? So basically the question is how to run javascript from server side code.

It's really easy:


protected void btnUser_Click(object sender, EventArgs e)
{
ClientScript.RegisterStartupScript(GetType(), "close", "window.close();", true);
}


You don't have to use the <script> tags when providing it with the last parameter set to true.

Apparently this wont work with firefox 2.0 and i cant seem to find a fix for this. For firefox <2.0 you can use the following:

window.open('','_parent','');
window.close();

Note: when using this in Internet Explorer it will ask you to close the window but if you add "window.open('','_parent','');" as above it wont!

Goodluck.

Friday, May 30, 2008

Webcontrol GridView with sorting

For everyone with the error:

The GridView "dgGridView" fired event Sorting which wasn't handled.

Here is the solution:

If you get the above error your allready set the AllowSorting="true" if not set it to your gridView.
Add to the grid an method for the event "sorting", when double click in the properties list it will create a new method for you which looks like this:


protected void gvProjectParts_Sorting(object sender, GridViewSortEventArgs e)
{
}


First we bind the data from SQL and put the datatable in the ViewState because we need this later.


protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataSet dataset = new DataSet();
SqlConnection conn = new SqlConnection("ConnectionString");
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand("select * from tblTable", conn);
adapter.Fill(dataset);
DataTable table = dataset.Tables[0];
if (table.Rows.Count > 0)
{
gvProjectParts.DataSource = table;
ViewState["gvProjectParts_DataSource"] = table;
gvProjectParts.DataBind();
}
}
}


Then we adjust the sort method where we use the saved viewstate, this is because gvProjectParts.DataSource and send.DataSource are empty:

protected void gvProjectParts_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable m_DataTable = (DataTable)ViewState["gvProjectParts_DataSource"];
if (m_DataTable != null)
{
DataView m_DataView = new DataView(m_DataTable);
m_DataView.Sort = e.SortExpression + " " + getSortDirection();
(sender as GridView).DataSource = m_DataView;
(sender as GridView).DataBind();
}
}

The function getSortDirection is explained here where we use the ViewState again to store the direction. This is because e.SortDirection is allways ASC.


private string getSortDirection()
{
string m_SortDirection;
if (ViewState["gvProjectParts_sortDirection"] == null)
m_SortDirection = "DESC";
else
m_SortDirection = (string)ViewState["gvProjectParts_sortDirection"];
switch (m_SortDirection)
{
case "ASC":
m_SortDirection = "DESC";
break;
case "DESC":
m_SortDirection = "ASC";
break;
}
ViewState["gvProjectParts_sortDirection"] = m_SortDirection;
return m_SortDirection;
}


Try it out !

Big thanks to Ryan Olshan and his post

Think it can also be done without using ViewState, please tell me how :)

Cheers,
Sjoerd

Monday, May 26, 2008

Rounded Corner Generator

I was looking today for a easy way to fix rounded corners on my div. I didnt want to use paint.net for cutting my own corners.

Following website creates these corners for you including the CSS and DIV code:

http://www.roundedcornr.com/

The following options are available:

- Basic RoundedCornr
- RoundedCornr with Gradient
- RoundedCornr with Border
- Single RoundedCornr Image ( for buttons ect. )

The standard weight x height for the RoundedCornr with Border is 1024 x 600. If you want to extend this open the _tl.png image and extend this one to your size.

Goodluck.

Monday, May 19, 2008

iTextSharp table is deprecated use PdfPTable instead

I was looking today for the function TableFitsPage, because it wasn't working as i expected it would be. Google turned up with a few results, this was one of them:

http://sourceforge.net/mailarchive/message.php?msg_id=003b01c7e0b1%24ad8869a0%246801a8c0%40abraxas.local

This post says: "Use a PdfPTable instead of a Table. Table is not supported anymore"

I never heard of PdfPTable even in the tutorials the dont mention it. Think they should make it deprecated in the library so people will know it's not supported anymore. Anyways the example from my last article uses the Table class.

This is the same example but with PdfPTable:


protected void Page_Load(object sender, EventArgs e)
{
//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\test.pdf", FileMode.Create));
//Open the document
document.Open();


#region Example2
//Start table with 2 columns
//Set the withs for the columns to 10% and 90%
PdfPTable table = new PdfPTable( new float[] { 10, 90 });
table.WidthPercentage = 100;

//Add first cell with colspan2
PdfPCell firstCell = new PdfPCell(new Phrase("Colspan Cell", FontFactory.GetFont(FontFactory.HELVETICA, 14, Color.BLACK)));
firstCell.Colspan = 2;
firstCell.VerticalAlignment = Element.ALIGN_TOP;
firstCell.BorderWidthBottom = 0.5f;
table.AddCell(firstCell);

//Add more cells
for (int i = 0; i < 10; i++)
{
PdfPCell moreCells = new PdfPCell(new Phrase("Cell " + i.ToString(), FontFactory.GetFont(FontFactory.HELVETICA_OBLIQUE, 12)));
moreCells.VerticalAlignment = Element.ALIGN_TOP;
moreCells.Colspan = 1;
moreCells.BorderWidth = 0.5f;
table.AddCell(moreCells);
}
//Add table to document
document.Add(table);
#endregion


//Close the document
document.Close();
}


Cell -> PdfPCell
Chunk -> Phrase
Table - > PdfPTable


Goodluck.

Sunday, May 18, 2008

Create PDF files in memory and mail them as an attachment

In my previous post i showed how to create an PDF file on-the-fly with iTextSharp.

Now we pick up the first HELLO WORLD example and dont write it to C:\text.pdf but to a MemoryStream. After that we mail it as an attachment.

As you will see it's no rocket science!



protected void Page_Load(object sender, EventArgs e)
{
//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer and write to memory
MemoryStream myStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, myStream);
//Open document
document.Open();

#region Example1
//Set some document attributes
document.AddTitle("Hello world");
document.AddAuthor("Sjoerd Perfors");
document.AddSubject("This is my first PDF created on: " + DateTime.Now.ToShortDateString());
//Add an image
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance("c:\\caesar_coin.jpg");
document.Add(image);
//Add a normal text
document.Add(new Chunk("HELLO WORLD", FontFactory.GetFont(FontFactory.HELVETICA, 18, Color.RED)));
//Add text to a specific position
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
cb.SetFontAndSize(bf, 12);
cb.ShowTextAligned(Element.ALIGN_RIGHT, "Another text placed on 100,400", 100, 400, 0);
cb.EndText();
#endregion

//Close the document
document.Close();

//Copy the stream to another stream and close it.
MemoryStream pdfstream = new MemoryStream(myStream.ToArray());
myStream.Close();
//Use the stream to send email
string fromEmail = "someone@someplace.com";
string toEmail = "someone@thisplace.com";
string body = "BODY";
string titel = "Sending your personal on the fly created PDF!!";

try
{
//Create the mailmessage object.
MailMessage objEmail = new MailMessage(fromEmail, toEmail, titel, body);
//Add the stream as attachemnt.
objEmail.Attachments.Add(new Attachment(pdfstream, "yourpdf.pdf"));
//Create the smtpclient with a SMTPserver defined in your web.config.
SmtpClient emailClient = new SmtpClient(ConfigurationManager.AppSettings["SMTPServer"]);
//Send the mail
emailClient.Send(objEmail);
//Close the stream
pdfstream.Close();
}
catch (Exception exc)
{
Console.WriteLine("Send failure: " + exc.ToString());
}
}


Goodluck!

How to create on-the-fly FREE PDF files in C# Asp.net with tables/images/page numbering and more!

Hi there, been a while since my last post..

Today i will show how to create "on the fly" PDF files. I used this for an web application where users have a "personal" PDF file in their mailbox.

There are many library's available for creating PDF files. This site will show a list of open source library's: csharp-source.net/open-source/pdf-libraries

Some of them i have tried:

Report.NET
SharpPDF
PDFsharp

but i think the easiest to use is iTextSharp.

The homepage of iTextSharp is: http://sourceforge.net/projects/itextsharp/ Here you can download the library, source code and examples.

Short description from the iTextSharp homepage:

"iText# (iTextSharp) is a port of the iText open source java library written entirely in C# for the .NET platform. iText# is a library that allows you to generate PDF files on the fly. It is implemented as an assembly."

The example project creates a large amount of PDF files to show what can be done with iTextSharp. You will have to comment a lot in order to get it working but after that it can come handy. This is because the examples project was build on an earlier version of iTextSharp.

Here are some tutorials for iTextSharp:

itextsharp.sourceforge.net/tutorial/index.html
www.aspfree.com/c/a/BrainDump/Working-with-iTextSharp/ ( found this while writing this article )

OK lets start Visual studio!

First we need to add a reference to the iTextSharp library:

references -> add reference -> browse -> select itextsharp.dll

Then we can include the following to our class:

using iTextSharp.text.pdf;
using iTextSharp.text;

and for file access:

using System.IO;

First we write the hello world with an image and some texts:


protected void Page_Load(object sender, EventArgs e)
{
//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\test.pdf", FileMode.Create));
//Open the document
document.Open();
//Set some document attributes
document.AddTitle("Hello world");
document.AddAuthor("Sjoerd Perfors");
document.AddSubject("This is my first PDF created on: " + DateTime.Now.ToShortDateString());
//Add an image
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance("c:\\caesar_coin.jpg");
document.Add(image);
//Add a normal text
document.Add(new Chunk("HELLO WORLD", FontFactory.GetFont(FontFactory.HELVETICA, 18, Color.RED)));
//Add text to a specific position
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
cb.SetFontAndSize(bf, 12);
cb.ShowTextAligned(Element.ALIGN_RIGHT, "Another text placed on 100,400", 100, 400, 0);
cb.EndText();
//Close the document
document.Close();
}

See how easy it is?

Remember that the X and Y positions are calculated from the bottomleft and not from the topleft.

The following example shows how to create an table with 2 columns
TABLE IS DEPRECATED SEE MY NEW POST WITH A EXAMPLE USING PdfPTable


#region Example2
//Start table with 2 columns
iTextSharp.text.Table table = new iTextSharp.text.Table(2);
table.BorderWidth = 0;
table.Padding = 2;
//Set the withs for the columns to 10% and 90%
float[] headerwidths = { 10, 90 };
table.Widths = headerwidths;
table.Width = 100;

//Add first cell with colspan2
Cell firstCell = new Cell(new Chunk("Colspan Cell", FontFactory.GetFont(FontFactory.HELVETICA, 14, Color.BLACK)));
firstCell.Colspan = 2;
firstCell.VerticalAlignment = Element.ALIGN_TOP;
firstCell.BorderWidthBottom = 0.5f;
table.AddCell(firstCell);

//Add more cells
for (int i = 0; i < 10; i++)
{
Cell moreCells = new Cell(new Chunk("Cell "+ i.ToString() , FontFactory.GetFont(FontFactory.HELVETICA_OBLIQUE,12)));
moreCells.VerticalAlignment = Element.ALIGN_TOP;
moreCells.Colspan = 1;
moreCells.BorderWidth = 0.5f;
table.AddCell(moreCells);
}
//Add table to document
document.Add(table);
#endregion


To add some nice functions like page numbering or footers we have to create a new class which extends the class PdfPageEventHelper. This class has the following handy functions:


public virtual void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title);
public virtual void OnChapterEnd(PdfWriter writer, Document document, float position);
public virtual void OnCloseDocument(PdfWriter writer, Document document);
public virtual void OnEndPage(PdfWriter writer, Document document);
public virtual void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, string text);
public virtual void OnOpenDocument(PdfWriter writer, Document document);
public virtual void OnParagraph(PdfWriter writer, Document document, float paragraphPosition);
public virtual void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition);
public virtual void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title);
public virtual void OnSectionEnd(PdfWriter writer, Document document, float position);
public virtual void OnStartPage(PdfWriter writer, Document document);


To use the functions we create a new class and overides above functions with out own code to create a nice footer:


public class PDFPageEvents: PdfPageEventHelper
{
PdfPTable table;
PdfTemplate tpl;
BaseFont helv;

public override void OnOpenDocument(PdfWriter writer, Document document)
{
table = new PdfPTable(2);
// initialization of the template
tpl = writer.DirectContent.CreateTemplate(100, 100);
tpl.BoundingBox = new Rectangle(-20, -20, 100, 100);
// initialization of the font
helv = BaseFont.CreateFont("Helvetica", BaseFont.WINANSI, false);
}

public override void OnEndPage(PdfWriter writer, Document document)
{
if (document.PageNumber == 1)
return;
PdfContentByte cb = writer.DirectContent;
cb.SaveState();
// write the headertable
float[] floatwidth = { (document.Right - document.Left) };
table.TotalWidth = 100;
//table.SetTotalWidth(floatwidth);
table.WriteSelectedRows(0, -1, document.Left, document.PageSize.Height - 50, cb);
// compose the footer
String text = "Page " + writer.PageNumber + " of ";

float textSize = helv.GetWidthPoint(text, 12);
float textBase = document.Bottom - 20;
cb.BeginText();
cb.SetFontAndSize(helv, 12);

float adjust = helv.GetWidthPoint("0", 12);
cb.SetTextMatrix(document.Right - textSize - adjust, textBase);
cb.ShowText(text);
cb.EndText();

cb.AddTemplate(tpl, document.Right - adjust, textBase);

cb.SaveState();
}

public override void OnCloseDocument(PdfWriter writer, Document document)
{
tpl.BeginText();
tpl.SetFontAndSize(helv, 12);
tpl.SetTextMatrix(0, 0);
tpl.ShowText("" + (writer.PageNumber - 1));
tpl.EndText();
}
}


Now in our previous example we add the following:


//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\test.pdf", FileMode.Create));
PDFPageEvents pageEvent = new PDFPageEvents();
writer.PageEvent = pageEvent;
//Open the document
document.Open();
document.Add(new Chunk("This is a new page WITHOUT page numbering."));
document.NewPage();
for (int i = 0; i < 5; i++)
{
document.Add(new Chunk("This is a new page WITH page numbering."));
document.NewPage();
}
//Close the document
document.Close();


In the next article i will descripe how to create an PDF in memory and mail this as an attachment.

Goodluck and big thanks for iTextSharp!

Friday, April 18, 2008

C# MD5 Encrypt and Random password generator

I think these functions can come handy for anyone who is developing C# webpages.

First function generates an random password with the given length:


public string GetRandomPasswordUsingGUID(int length)
{
// Get the GUID
string guidResult = System.Guid.NewGuid().ToString();
// Remove the hyphens
guidResult = guidResult.Replace("-", string.Empty);
// Make sure length is valid
if (length <= 0 length > guidResult.Length)
throw new ArgumentException("Length must be between 1 and " + guidResult.Length);
// Return the first length bytes
return guidResult.Substring(0, length);
}


Second function Encodes the given string to an MD5 string.


public string EncodePassword(string originalPassword)
{
//Declarations
Byte[] originalBytes;
Byte[] encodedBytes;
MD5 md5;
//Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
md5 = new MD5CryptoServiceProvider();
originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
encodedBytes = md5.ComputeHash(originalBytes);
//Convert encoded bytes back to a 'readable' string
return BitConverter.ToString(encodedBytes);
}


Last function i ripped of an other site, im not sure which one it was. Credits for him/her :-)

Goodluck,
Sjoerd

Thursday, April 17, 2008

Compile .resx to .resources files from .NET 1.0 projects.

I found out today that old .resx files from .Net 1.0 projects wont compile automatically. You have to do this by your self after a change in it!

resgen.exe will do this for you. This little program is somewhere in your visual studio folder:

resgen.exe test.resx test.resources

This will compile the resx file to a binairy resources file.

You can add this to your tools in Visual Studio (i used 2005). So you dont need to open an command prompt window each time:

Tools -> External Tools -> Add ->

Title: Build .resource file
Command: C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\SDKTools\resgen.exe
Arguments: $(ItemPath)
Initial directory: $(ItemDir)
[v] use output window

This will compile the current opend resx file to a resource file in the same directory.

Here's my output:

Read in 150 resources from 'D:\Projecten\***\TextRes-EN.resx'
Writing resource file... Done.

Goodluck!

C# System.Configuration.ConfigurationSettings.AppSettings is obsolete !

Today, when i was building an old project, i got the following warning:

Warning 10 'System.Configuration.ConfigurationSettings.AppSettings' is obsolete: 'This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.AppSettings'

With the following line of code:

SmtpClient emailClient = new SmtpClient(ConfigurationSettings.AppSettings["SMTPServer"]);

Oke so just replace it right? ..Not working:

SmtpClient emailClient = new SmtpClient(System.Configuration.ConfigurationManager.AppSettings["SMTPServer"]);

ConfigurationManager not found...

The thing is they packed the ConfigurationManager in another dll file, which you need to add as reference.

right-click References -> add reference -> select System.Configuration in .NET tab

Et voila following code works:

SmtpClient emailClient = new SmtpClient(ConfigurationManager.AppSettings["SMTPServer"]);


Hope this will help anyone.

Tuesday, April 1, 2008

UUencode and UUdecode in C#.net

I was looking today for a new UUencode function and my colleague ended up with the following class which works like a charm. This one is really fast.


using System;
using System.Text;
public static class Codecs
{
static
readonly byte[] UUEncMap = new byte[]
{
0x60, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,
0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49,
0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
0x57,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
};
static readonly
byte[] UUDecMap = new byte[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22,
0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A,
0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
public static void UUDecode(System.IO.Stream input,
System.IO.Stream output)
{
//if (input == null)
// throw new
ArgumentNullException("input");
//if (output == null)
// throw new
ArgumentNullException("output");
long len = input.Length;
if (len ==
0)
return;
long didx = 0;
int nextByte = input.ReadByte();
while
(nextByte >= 0)
{
// get line length (in number of encoded
octets)
int line_len = UUDecMap[nextByte];
// ascii printable to 0-63 and
4-byte to 3-byte conversion
long end = didx + line_len;
byte A, B, C,
D;
if (end > 2)
{
while (didx < a =" UUDecMap[input.ReadByte()];" b =" UUDecMap[input.ReadByte()];" c =" UUDecMap[input.ReadByte()];" d =" UUDecMap[input.ReadByte()];">> 4) & 3)));
output.WriteByte((byte)(((B <<>> 2) & 15)));
output.WriteByte((byte)(((C
<< a =" UUDecMap[input.ReadByte()];" b =" UUDecMap[input.ReadByte()];">> 4) & 3)));
didx++;
}
if (didx < b =" UUDecMap[input.ReadByte()];" c =" UUDecMap[input.ReadByte()];">> 2) & 15)));
didx++;
}
// skip
padding
do
{
nextByte = input.ReadByte();
}
while (nextByte >=
0 && nextByte != '\n' && nextByte != '\r');
// skip end of
line
do
{
nextByte = input.ReadByte();
}
while (nextByte >= 0
&& (nextByte == '\n' nextByte == '\r'));
}
}
public static
void UUEncode(System.IO.Stream input, System.IO.Stream output)
{
//if
(input == null)
// throw new ArgumentNullException("input");
//if (output
== null)
// throw new ArgumentNullException("output");
long len =
input.Length;
if (len == 0)
return;
int sidx = 0;
int line_len =
45;
byte[] nl = Encoding.ASCII.GetBytes(Environment.NewLine);
byte A, B,
C;
// split into lines, adding line-length and line terminator
while (sidx
+ line_len < end =" sidx" a =" (byte)input.ReadByte();" b =" (byte)input.ReadByte();" c =" (byte)input.ReadByte();">> 2) &
63]);
output.WriteByte(UUEncMap[(B >> 4) & 15 (A <<>> 6) & 3 (B << idx =" 0;" a =" (byte)input.ReadByte();" b =" (byte)input.ReadByte();" c =" (byte)input.ReadByte();">> 2) &
63]);
output.WriteByte(UUEncMap[(B >> 4) & 15 (A <<>> 6) & 3 (B << a =" (byte)input.ReadByte();" b =" (byte)input.ReadByte();">> 2) &
63]);
output.WriteByte(UUEncMap[(B >> 4) & 15 (A << a =" (byte)input.ReadByte();">> 2) & 63]);
output.WriteByte(UUEncMap[(A << idx =" 0;">


I call my function like this:

//First write to memory
MemoryStream
mmsStream = new MemoryStream();
StreamWriter srwTemp = new
StreamWriter(mmsStream);
//sBuffer is my encoded
text.
srwTemp.Write(sBuffer);
srwTemp.Flush();
mmsStream.Position =
0;
//Write to IO..filename is a localvar which
has the location of the file.
System.IO.FileStream stmStreamOut = new
System.IO.FileStream(filename, FileMode.OpenOrCreate);
//Calling
UUDecode
Codecs.UUDecode(mmsStream,
stmStreamOut);
stmStreamOut.Flush();
stmStreamOut.Close();
//Done


Goodluck.

Friday, March 28, 2008

Using Flash Charts in a Flex3 Application

If you're looking for Chart components to work with Flex applications:
- ILOG Elixir (Flex charts) http://www.ilog.com/products/elixir/
- Fusioncharts (Flash) is producing in a couple weeks support for Flex. http://www.fusioncharts.com/
- Anycharts (Flash)
http://www.anychart.com/blog/category/anychart-for-flex/


In this post i will try to create a wrapper for flash charts. This can also be handy when you're in a need of any Flash AS2 Components. I have seen some people doing it ( or saying they did it ) so it wouldn't be any problem...right?

Google brought me the following results which can be handy:

1 http://flexexamples.blogspot.com/2007/12/load-swf-from-outside-and-call-its.html
2 http://wiki.apexdevnet.com/index.php/Creating_Flex_Charts_Easily
3 http://kb.adobe.com/selfservice/viewContent.do?externalId=749eaa47&sliceId=1
4 http://www.fusioncharts.com/forum/Topic5068-28-1.aspx

Since these flashcharts all use ActionScript 2.0 they cant really communicate with Flex2/3 which uses AS 3.0. If i build an AS2.0 Wrapper Flash that communicates trough localconnection with my flex application and also communicates with the chart object then it should work.

First i will use the FusionCharts ( http://www.blogger.com/www.fusioncharts.com/LiveDemos.asp ) ( since most examples use them ) then i will try the amCharts ( www.amcharts.com/ ).

Here's what i want to do:

- Create a wrapper flash object to communicate between Flex and the Flash chart
- Setup a link in Flex to use the Wrapped Flash object.
- Building a chart with XML data from Flex
- Doing the same with amCharts

First i need to install Flash CS3 to create the wrapper, but then i never used Flash CS3..

Following code is for my wrapper class and will change the text:





//local Connection with flex
var flash_flex:LocalConnection = new
LocalConnection();
//here connection can be made inter-domain
flash_flex.allowDomain("*");
flash_flex.connect("flex_connector");
flash_flex.allowInsecureDomain("*");
flash_flex.changeText =
function(test : String):Void
{
TEXTBOX.text = test;
}


In flash:
- choose to create a new flash file with AS2.0
- create an text object on the screen
- Change the instance name to TEXTBOX
- Change to dynamic text
- Right click on the timeframe and choose for "Actions"
- A code like editor comes up, paste the code above on it and close it.
- Export this using Flash7 and AS2.0 to an SWF file and call it WRAPPER.swf


Now in flex create an localconnection and call the function with one parameter:

MXML





<mx:SWFLoader source="WRAPPER.swf" scaleContent="true" width="300" height="300" x="10" y="10"></mx:SWFLoader>
<mx:Button x="374" y="57" label="Button" click="click();"></mx:Button>


AS




import mx.states.State;
import mx.events.SliderEvent;
import
mx.controls.Alert;
import flash.net.LocalConnection;
[Bindable]
public
var lc:LocalConnection;
private function initApp() : void
{
lc = new
LocalConnection();
lc.allowInsecureDomain("*");
}
private function
click():void
{
lc.send("flex_connector", "changeText","THIS IS A TEST");
}

Oke run and works like a charm.. or doesnt it?

Next thing is loading the chart files...

Here's how i changed the wrapper function:

1. Added a symbol containing MovieClip
2. Giving it as name MC ( its case sensitive !! )
3. put it on X 0 and Y 0
4. Changed the code:



var flash_flex:LocalConnection = new
LocalConnection();
_root.flash_flex.allowDomain("*");
_root.flash_flex.allowInsecureDomain("*");
_root.flash_flex.connect("flex_connector");

flash_flex.methodToExecute = function(param1:String,param2:String) {
TEXTBOX.text = param1;
_root.flash_flex.close();
/*_root.chartWidth = 400;
_root.chartHeight = 400;
_root.strXML = param2;
_root.MC.chartWidth = 400;
_root.MC.chartHeight = 400;
_root.MC.strXML = param2;*/
_root.MC.loadMovie(param1);
_root.param2 = param2;
_root.interid = setInterval(interFunc,1000);

};


function interFunc(){
clearInterval(_root.interid);

_root.MC.setDataXML(_root.param2);
_root.MC._height = 200;
_root.MC._width = 400;
_root.MC._x = 0;
_root.MC._y = 0;
_root._height = 400;
_root._width = 400;
_root._x = 0;
_root._y = 0;
TEXTBOX.text = _root.param2;
}

And here are my changes to the Flex code:




<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initApp()">
<mx:Panel x="0" y="0" width="492" height="486" layout="absolute" title="Flash 8 SWF">
<mx:SWFLoader source="WRAPPER.swf" scaleContent="false" width="400" height="400" x="36" y="10"/>


</mx:Panel>
<mx:Button x="435" y="10" label="Button" click="click();"></mx:Button>
<mx:Script>
<![CDATA[
import mx.states.State;
import mx.events.SliderEvent;
import mx.controls.Alert;
import flash.net.LocalConnection;

[Bindable]
public var lc:LocalConnection;
public var myXML:String="<chart><set label='A' value='10' /><set label='B' value='11' /></chart>";
private function initApp() : void
{
lc = new LocalConnection();
lc.allowInsecureDomain("*");
}

private function click():void
{
lc.send("flex_connector", "methodToExecute","Column3D.swf?flashId=MC&chartWidth=400&chartHeight=300",myXML);
}



]]>
</mx:Script>
</mx:Application>


Next problem is the scale, now i have a column chart but not 400x400.. the scale is weird. Sorry but i haven't figured this out yet.

Ok from here i make a jump to amCharts since FusionCharts is making a Flex compatible version. Following code creates an amChart with variables from Flex. Be sure to have the following files in your bin map:

amcolumn.swf
amcolumn_data.xml ( from examples)
amcolumn_settings.xml ( from examples)

Forget the symbols and text object from the project above.
Create a clean flash file and put this in actions:


var flash_flex:LocalConnection = new LocalConnection();
_root.flash_flex.allowDomain("*");
_root.flash_flex.allowInsecureDomain("*");
_root.flash_flex.connect("flex_connector");

_root.flash_flex.methodToExecute = function(chartswf:String)
{
_root.createEmptyMovieClip("holder", this.getNextHighestDepth());
holder.loadMovie(chartswf);
};


And here's the flex code:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="initApp()">
<mx:SWFLoader id="mySWFLOADER" source="WRAPPER.swf" scaleContent="false" width="500" height="500" x="0" y="0"/>
<mx:Button x="435" y="10" label="Button" click="click();"></mx:Button>
<mx:Script>
<![CDATA[
import mx.states.State;
import mx.events.SliderEvent;
import mx.controls.Alert;
import flash.net.LocalConnection;
[Bindable]
public var lc:LocalConnection;
private function initApp() : void
{
lc = new LocalConnection();
lc.allowInsecureDomain("*");
}
private function click():void
{
lc.send("flex_connector", "methodToExecute","amcolumn.swf?settings_file=amcolumn_settings.xml&data_file=amcolumn_data.xml&flash_width="+mySWFLOADER.width+"&flash_height="+mySWFLOADER.height);
}
]]>
</mx:Script>
</mx:Application>




So far this post, good luck creating wrappers!

C#.net communicating with UDT types in Oracle.

First headache on this blog.

Im trying to call a function in oracle which needs an custom type object in C#.net. To achieve this you need the new Oracle ODP.net client software.

note: If you want to connect to any Oracle database you have to get a oracle client, its not like MS SQL which has build in reference and you're ready to go.

The ODP.net software with Visual Studio Tools can be found here: http://www.oracle.com/technology/software/tech/windows/odpnet/index.html

You can use an 11g client on an Oracle 9i database! Please also install the Visual studio tools you need these later.

After installing the client you need to adjust the following 2 files for your connection:

tnsnames.ora and sqlnet.ora

My tnsnames is like this:


filki.omnext.net =
(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=filki.omnext.net)(PORT=1521)))(CONNECT_DATA=(SID=filki)(SERVER=DEDICATED)))


In visual studio the connection string would be:

"Data Source=filki.omnext.net;UserID=test;Password=secret;"

Now you can set your Client to connect in Visual Studio with Oracle, this is all wizzard and shouldn't be any problem :). After connection you can see your custom types created in Oracle. Right click on the type and select generate class files! After that you have a nice C# class of your UDT from Oracle.

The function and my UDT im calling in Oracle is like this:

CREATE OR REPLACE TYPE TEST.T_NUMBER_FIELD AS
OBJECT
(
AVALUE NUMBER(8) ,
COLOUR_CODE NUMBER(2)
);
/
CREATE OR REPLACE TYPE TEST.T_VARCHAR_FIELD AS OBJECT
(
AVALUE
VARCHAR2(20) ,
COLOUR_CODE NUMBER(2)
);
/
CREATE OR REPLACE TYPE
TEST.T_CONTAINER AS OBJECT
(
BOEKING T_VARCHAR_FIELD ,
EENHEID_NUMMER T_VARCHAR_FIELD ,
GEWICHT T_NUMBER_FIELD ,
X_POS
T_NUMBER_FIELD ,
Y_POS T_NUMBER_FIELD ,
Z_POS T_NUMBER_FIELD ,
MEMBER PROCEDURE INIT
);
/
CREATE OR REPLACE TYPE BODY
TEST.T_CONTAINER
AS
MEMBER PROCEDURE INIT
IS
BEGIN
SELF :=
T_CONTAINER(T_VARCHAR_FIELD(NULL, NULL), T_VARCHAR_FIELD(NULL, NULL),
T_NUMBER_FIELD(NULL, NULL),
T_NUMBER_FIELD(NULL, NULL), T_NUMBER_FIELD(NULL,
NULL), T_NUMBER_FIELD(NULL, NULL));
END;
END;
/
CREATE OR
REPLACE FUNCTION TEST.FUNCTION1 ( P_CONTAINER_GEGEVENS IN OUT T_CONTAINER )
RETURN T_CONTAINER
IS
V_COLOUR_CODE NUMBER(2) := 0;
BEGIN
V_COLOUR_CODE := 4;
P_CONTAINER_GEGEVENS.BOEKING.COLOUR_CODE :=
V_COLOUR_CODE;
P_CONTAINER_GEGEVENS.EENHEID_NUMMER.COLOUR_CODE :=
V_COLOUR_CODE;
P_CONTAINER_GEGEVENS.GEWICHT.COLOUR_CODE := MOD(V_COLOUR_CODE
+ 3, 10);
P_CONTAINER_GEGEVENS.X_POS.COLOUR_CODE := MOD(V_COLOUR_CODE + 1,
10);
P_CONTAINER_GEGEVENS.Y_POS.COLOUR_CODE := MOD(V_COLOUR_CODE + 1, 10);
P_CONTAINER_GEGEVENS.Z_POS.COLOUR_CODE := MOD(V_COLOUR_CODE + 1, 10);
RETURN P_CONTAINER_GEGEVENS;
END;
/

Now in C# i have created the following function to call my Oracle function with my C# UDT's

private T_CONTAINER colorContainer()
{
//Connection to Oracle
OracleConnection oraclecon = new OracleConnection("Data
Source=filki.omnext.net;User ID=test;Password=secret;");
//Oracle PL/SQL
Function.
OracleCommand colourCommand = new OracleCommand("FUNCTION1",
oraclecon);
//It has to be a stored procedure.
colourCommand.CommandType
= CommandType.StoredProcedure;
//Create my C# UDT class with values
T_CONTAINER curContainer = new T_CONTAINER();
curContainer.EENHEID_NUMMER = new T_VARCHAR_FIELD(tbEenheidNummer.Text);
curContainer.BOEKING = new T_VARCHAR_FIELD(tbBoeking.Text);
curContainer.GEWICHT = new T_NUMBER_FIELD(Decimal.Parse(tbGewicht.Text));
curContainer.X_POS = new T_NUMBER_FIELD(numXPositie.Value);
curContainer.Y_POS = new T_NUMBER_FIELD(numYPositie.Value);
curContainer.Z_POS = new T_NUMBER_FIELD(numZPositie.Value);
//Parameter
OUT - first send the return value!!
OracleParameter colourOutParameter = new
OracleParameter();
colourOutParameter.OracleDbType = OracleDbType.Object;
colourOutParameter.Direction = ParameterDirection.ReturnValue;
colourOutParameter.ParameterName = "P_CONTAINER_GEGEVENS2";
colourOutParameter.UdtTypeName = "TEST.T_CONTAINER";
colourOutParameter.Value = new T_CONTAINER();
//Parameter IN - object
the container object to send as input.
OracleParameter colourInParameter =
new OracleParameter();
colourInParameter.OracleDbType = OracleDbType.Object;
colourInParameter.Direction = ParameterDirection.Input;
colourInParameter.ParameterName = "P_CONTAINER_GEGEVENS";
colourInParameter.UdtTypeName = "TEST.T_CONTAINER";
colourInParameter.Value = curContainer;
//Parameters to add, first OUT
then IN
colourCommand.Parameters.Add(colourOutParameter);
colourCommand.Parameters.Add(colourInParameter);
//Connection open
if (oraclecon.State == ConnectionState.Closed)
oraclecon.Open();
//Call the function.
try
{
colourCommand.ExecuteNonQuery();
}
catch (OracleException ex)
{
MessageBox.Show(ex.ToString(),
"Oracle exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
oraclecon.Close();
return null;
}
//Connection close
oraclecon.Close();
//Here's the object with filled in values.
return
(T_CONTAINER)colourCommand.Parameters[0].Value;
}

Remember that the return value have to come first because for SOME reason it wont work!

Here's the form which helped me alot, i also posted my problem there:
http://forums.oracle.com/forums/thread.jspa?threadID=386484


Thanks for reading, and goodluck.

-Sjoerd

Thursday, March 27, 2008

First post

Hello there,

The reason i started this blog is because i had a lot of headaches last year and i want to share those to the world. From frustrating simple problems to complex never ending google searches. All combined with lovely solutions or ugly walkarrounds.

Hope i can keep this blog alive (which i suppose is up to my headaches) and save some ones day for having the same headache!

Enjoy,

Sjoerd