Tuesday 12 May 2009

Import Data from Google Analytics VB.NET

As far as I know there is no current service available for consuming data from Google Analytics. The way I got round this was by setting up my analytics account to email me xml reports and then setting up an application to check the email account for them. When the application gets an email from Google it consumes the xml. It's best to set up a dedicated email address for analytics and save each xml document as they come in, just in case you want to change what you consume to your database at a later date and need to pull the whole lot back in again.

First get the (free) Indy Sockets dll from:
http://www.indyproject.org/index.en.aspx

The Code
' create a pop3 client using indie
Dim pop3 As New Indy.Sockets.POP3
pop3.Username = "******" 'the name of the account you get analytics to email reports to
pop3.Password = "****" 'password of the account
pop3.Host = "******" 'your mail host
pop3.Connect()

Dim nrOfMsgs As Integer = pop3.CheckMessages

For i As Integer = 1 To nrOfMsgs
Dim msg As New Indy.Sockets.Message
'get message
pop3.Retrieve(i, msg)

'attatchments
'ANALYTICS DATA

For x As Integer = 1 To msg.MessageParts.Count - 1 'search through the message parts
Dim att As Indy.Sockets.Attachment
Dim isAtt As Boolean = False

Try
att = CType(msg.MessageParts.Items(x), Indy.Sockets.Attachment)
isAtt = True
Catch
End Try
Dim ct As String = msg.MessageParts.Items(x).ContentType
If isAtt = True And InStr(msg.Subject, "the subject expected") > 0 Then
Dim stream As New Indy.Sockets.TIdNetMemoryStream
att.SaveToFile("c:\analytics\" & Now.Year & Now.Month & Now.Day & "-" & Now.Hour & Now.Minute & Now.Second & ".xml")

'here you can do whatever you like with the xml document, add all the data to your sql
'database!

End If


Next

pop3.Delete(i) 'delete the email from the server

Next




pop3.Disconnect()
pop3.Dispose()

Monday 11 May 2009

This row already belongs to another table ASP.NET

Just a quick look at a problem I came across when trying to copy rows from one datatable to another.

I originally tried this:

for i as integer = 0 to DT.rows.count - 1
newDT.rows.add(DT.rows(i))
next

ASP.NET threw a hissy fit at me and gave me the "This row already belongs to another table" error. I haven't looked to far into this but I assume the datarow objects are bound to a row schema inherited from the datatable schema. A bit of googling led me to the following solution:


for i as integer = 0 to DT.rows.count - 1
newDT = DT.Clone
newDT.ImportRow(DT.Rows(i))
next

So there we go, the clone function copies the schema from the first table to the second which allows for the importing of our rows.

Tuesday 5 May 2009

Posting an Image to a Web Page in asp.net

I recently had to write an application that was able to upload images to a website in order to be filed away and used by it's photo gallery pages. All I did to put this in place was make a timer which periodically checked for new images in a local folder. When it finds new images it loops through the files and passes each image to a posting function. After a successful post the image gets archived away by the local application. The website performs it's own local file and database functions to file away the image and the job is done! Let's look at some snippets:

The business end of the windows app....

Dim postURL as string = "http://www.yourwebsite.com/somepage.aspx"

Private Sub uploadImage(ByVal theImage As Image, ByVal filename As String)

theImage = processImage(theImage) 'this is a function I use for some intelligent resizing of the image
Dim tempFileName As String = Path.GetTempFileName
theImage.Save(tempFileName)

Dim myHTTPRequest As New WebClient
Dim myHTTPResponse As Byte() = myHTTPRequest.UploadFile(postURL, "POST", tempFileName)

End Sub


The website code to get the image...

Page.Response.ContentType = "image/jpg"


Dim myimage As Byte() = New Byte(Page.Request.ContentLength - 1) {}
Dim uppedImage As HttpPostedFile = Request.Files.Item(0)
uppedImage.InputStream.Read(myimage, 0, CInt(Request.Files.Item(0).ContentLength))


Dim theImage As Image
theImage = Image.FromStream(uppedImage.InputStream())
theImage.Save("C:\mylocalsite\" & getImageName() & ".jpg") 'getImageName just returns a unique date stamped file name

Monday 4 May 2009

Creating Image Watermarks in VB.NET

Fancy making your own batch watermarking application? Here's a function that'll get you started. I originally adapted this from some code that was serving images in asp.net watermarked at runtime using a http handler. That was pretty nifty but I really needed it to watermark images for some automated uploading to facebook.


Public Function AddWaterMark(ByVal theImage As Image) As Image


Dim canvas As Graphics


'create a new bmp the size of the passed image
Dim bmpNew As Bitmap = New Bitmap(theImage.Width, theImage.Height)
'create a canvas
canvas = Graphics.FromImage(bmpNew)


'draw the passed image onto the canvas
canvas.DrawImage(theImage, New Rectangle(0, 0, _
bmpNew.Width, bmpNew.Height), 0, 0, _
theImage.Width, theImage.Height, GraphicsUnit.Pixel)
theImage = bmpNew



Dim overlayImg As Bitmap


'make the overlay image
overlayImg = Drawing.Image.FromFile("C:\someplace\mywatermark.png", True)

'draw the overlay onto the top left corner
canvas.DrawImage(overlayImg, 0, 0, overlayImg.Width, overlayImg.Height)

Dim tempImage As Image = bmpNew
AddWaterMark = tempImage



End Function

Sunday 3 May 2009

Stylesheets for Different Web Browsers

If you're like me and you are required to keep the websites you develop accessible to 95%+ of your customer base then making patch style sheets is a good way to go. To keep everything neat I develop a site with IE7 and FF3 open, testing in each periodically. At the end of the development process I open ie6 and, after my eyes have finished throwing up, I throw in an ie6 only stylesheet to begin the clear up. This stylesheet is called last so that I can override anything in my other css.


<!--ie 6 only!-->
<!--[if IE 6]-->
<link href="/css/ie6.css" rel="stylesheet" type="text/css">
<!--[endif]-->
<!--/ie 6 only!-->





I like this way of doing things since it makes it a lot easier to dive in and out of, allows me to code the rest of the site free of ie6 restrictions but still lets me cater for those 15% of our visitors that still insist on using ie6. Plus I like the fact that in a year or two, when that 15% is closer to 0%, I can easily remove all my ie6 fixes with a simple edit to my master pages.

Other html if statements include:



<!--[if IE 7]-->
<link rel="stylesheet" type="text/css" href="css/ie7.css">
<!--[endif]-->




IE7 only stylesheet for resolving any ie7 quirks.

<!--[if !IE]-->
<link rel="stylesheet" type="text/css" href="/css/nonIE.css">
<!--[endif]-->



A stylesheet for all browsers except for versions of internet explorer.