Uncategorized » Page 4

Category: Uncategorized

Using Google Spreadsheets to Collect Form Data

Google Spreadsheets recently offered the ability to create a form that will collect customer information into the spreadsheet. This is great for people that don’t have access to storing data in a traditional database (which is our preferred solution). They offer you the code to either link to for this form, email the code (great for emailed surveys) as well as code to embed (via IFrame) the form in your existing web page.

If you’d prefer to have FULL control over the display of the form and control the formatting and manipulation of data with your server-side code here is a handy little guide on how to do this using PHP.

 

  1. Create Google Doc form with all the fields your form needs
    image
  2. Save the form
    image
  3. Email yourself a copy of the form
    image
  4. Pull the necessary fields out of the email to generate the form
    URL for curl to post to
    URL to post form to...
    Names of the various input fields
    Finding the name of the various fields
  5. Insert code below into PHP page
  6. Test solution
   1: //In order to post to Google Spreadsheet Form

   2: //http://spreadsheets.google.com/formResponse?formkey=dFdYSTlzUVJsSomeReallyLongKeyGoesHereqemU2YUE6MA..

   3: //Name "entry.0.single" 

   4: //Email is "entry.1.single"

   5: //Phone is "entry.2.single"

   6: //Comment is "entry.3.single"

   7: //IP address is "entry.4.single"

   8: $url = 'http://spreadsheets.google.com/formResponse?formkey=dFdYSTlzUVJsSomeReallyLongKeyGoesHereqemU2YUE6MA..';

   9: // Create post array to send results to Google Spreadsheets

  10: $fields = array(

  11:                         'entry.0.single'=>urlencode($name),

  12:                         'entry.1.single'=>urlencode($email),

  13:                         'entry.2.single'=>urlencode($phone),

  14:                         'entry.3.single'=>urlencode($comments),

  15:                         'entry.4.single'=>getRealIpAddr(),

  16:                         'submit'=>'submit'

  17:                 );

  18:  

  19: // Begining of code for posting to Google Spreadsheet

  20: $fields_string = '';

  21: //url-ify the data for the POST

  22: foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }

  23: //rtrim($fields_string,"& ");

  24: $fields_string = substr($fields_string, 0, strlen($fields_string)-1); 

  25: $result = "Fields_String: [" . $fields_string . "]<br />";

  26:  

  27: //set POST variables for Google Spreadsheets

  28: //open connection

  29: $ch = curl_init();

  30:  

  31: //set the url, number of POST vars, POST data

  32: curl_setopt($ch,CURLOPT_URL,$url);

  33: curl_setopt($ch,CURLOPT_POST,count($fields));

  34: curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);

  35: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

  36: curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');

  37:  

  38: //execute post

  39: $result .= "Curl Results: [" . curl_exec($ch) . "]<br />";

  40:  

  41: //close connection

  42: curl_close($ch);

Things to note about the above PHP code (gasp!) are that you need to define the proper URL to the spreadsheet and the correct number and names of  fields (see step 4 above) . The only one that might be a little odd is getRealIpAddr() method. This is defined elsewhere in the page’s code as follows:

   1: // Function to get real IP address in case visitor is behind a proxy server

   2: function getRealIpAddr()

   3: {

   4:     if (!empty($_SERVER['HTTP_CLIENT_IP'])) // Check IP from shared internet

   5:     {

   6:         $ip = $_SERVER['HTTP_CLIENT_IP'];

   7:     }

   8:     elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) // to check if ip is passed from proxy

   9:     {

  10:         $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];

  11:     }

  12:     else

  13:     {

  14:         $ip = $_SERVER['REMOTE_ADDR'];

  15:     }

  16:     return $ip;

  17: }

 

 

 

Have fun folks! If you want to rip into my code and/or have suggestions on better PHP coding styles, please use the comment section below…

Google Voice for Android Supports Non-Gmail Accounts!

The title says it all! Ever since I got my Google Voice account, I’ve not been able to use it with my Google ION phone (the latest developer platform phone) because I set up my phone using my Google Apps account rather than a Gmail account.

This presented a problem not only with Google Voice but also the Android Marketplace but that is a story for another day. Well, lo and behold, a new update notification showed up on my phone so I figured “why not?” After installing I noticed it now supports multiple addresses/accounts so I was able to put in the email address of my choice and Voila, it worked! Wooohooo….

Want to know more about Google Voice (sorry, still in invite mode and they don’t give us invites to hand out), watch this video…

Wave of the Future

I haven’t brought this up in the blog yet but have dropped some info about my trip last week to Google I/O 2009. While the Android phone was cool, the stellar announcement of the week was Google Wave. I'm not sure if I can sell you on the value of this jump in Internet technology so hopefully if you are interested in the least, you’ll be as excited about this as I was. So pour yourself a cup of coffee and be prepared to be amazed!

 

 

Once I get my login to the sandbox system and have some seat-time with the product, I’ll post my impressions here.

Thoughts? Let me know what you think about Wave!

Adding Bar Codes to Receipts in AspDotNetStorefront

Sample Administrative Notification ReceiptA recent posting in the AspDotNetStorefront forums got my brain spinning on how best to accomplish this. The technology to do this, once written, should be able to be leveraged in other areas that clients of mine have been looking to do. So, out comes Visual Studio and Google to come up for some starting points on how to accomplish this.

Research pointed me at an article by Zach Smith on TechRepublic that provided the basis for this project.  With this, I created a class file to place in the site’s /App_Code directory containing the following code:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;

namespace BarCode{public class BarCode
{
public static Bitmap CreateBarcode(string data)
{
// Create the Bitmap we'll be using.
Bitmap barCode = new Bitmap(1, 1);
// Get a reference to the Free 3 of 9 font. We'll use this to generate the barcode.
// Found at http://www.squaregear.net/fonts/free3of9.shtml
Font threeOfNine = new Font("Free 3 of 9", 60, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
// Get a graphics object to work with
Graphics graphics = Graphics.FromImage(barCode);
// Now we need to get the width and height that our data will cover 
// after is is rendered with the Free 3 of 9 font
SizeF dataSize = graphics.MeasureString(data, threeOfNine);
// Now we base the Bitmap's size off of this data
barCode = new Bitmap(barCode, dataSize.ToSize());
// Refresh our Graphics object with the new bitmap
graphics = Graphics.FromImage(barCode);
// Make the Graphic object's drawing surface white
graphics.Clear(Color.White);
// Set the rendering hint to SingleBitPerPixel
graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
// Draw the string onto the Graphics ojbect
graphics.DrawString(data, threeOfNine, new SolidBrush(Color.Black), 0, 0);
// Force the graphics object to execute any pending operations
graphics.Flush();
// Dispose of our objects
threeOfNine.Dispose();
graphics.Dispose();
// Return the finished barcode
return barCode;
}
}
}

One of the key features of this code is the font that is used to create the barcode. Matthew Welch has released a number of freely available TrueType fonts at his site I Shot the Serif. The font in question is his “Free 3 of 9” which will produce a 3 of 9, or Code 39, barcode that is scannable by my hand-held scanners. You will need to download the fonts and install them into the %windir%\font directory on the server running the storefront. One thing that is very important is that the font won’t be available until either the server is rebooted or you’ve run IISRESET on the server. Normally the font is available immediately as soon as it is added to the server’s font directory to most applications but working with IIS6 on a Win2k3 server and IIS7 on a Vista box required an IISRESET to enable the font.

Next, we need to create a file in the website that will will actually generate the barcode image on the fly. This is done in the code-behind of the CreateBarCode.aspx file:

// ------------------------------------------------------------------------------------------
// Copyright Exhibit A Communications, 2009.
// Portions copyright Zach Smith, http://blogs.techrepublic.com.com/howdoi/?p=173
// 
// THE ABOVE NOTICE MUST REMAIN INTACT. 
// ------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using AspDotNetStorefrontCommon;
using BarCode;
namespace AspDotNetStorefront {
/// <summary>
/// Summary description for createbarcode.
/// </summary>
public partial class createbarcode : System.Web.UI.;color: #2b91af">Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
string data = Request.QueryString["data"];
Response.ContentType = "image/gif";
Response.Clear();
Bitmap barCode = BarCode.BarCode.CreateBarcode("*" + data + "*");
barCode.Save(Response.OutputStream, ImageFormat.Gif);
Response.End();
barCode.Dispose();
}
}
}

You’ll notice that in the call to BarCode.BarCode.CreateBarcode() includes an asterisk before and after the actual code to be encoded into the barcode. This is because Code39 barcodes are supposed to be enclosed in asterisks in order for scanners to identify the barcode type. This simple file just takes the querystring value named “data” and passes it (after enclosing it in *) to the CreateBarcode() function in the BarCode class in the BarCode namespace.

Lastly we will need modify the XMLPackage to generate the call to this image. In my client’s case, they want this to show up in the administrative notification email which is printed for the order pickers. As such, I added the following code to the appropriate location in the notification.adminneworder.xml.config file that generates this email.

<tr>
<td colspan="2" align="center">
<img src="{/root/System/StoreUrl}createbarcode.aspx?data={$OrderInfo/OrderNumber}" alt="Order Number {/root/QueryString/ordernumber}" />
</td>
</tr>

In this case, the table row is inserted into the tblOrderHeader table generated by the order ID. Please note that I’ve used two different
methods to pull in the order number into the <img> tag for illustrative purposes; either one will work

Hopefully someone else will find this handy. If so, please leave a note in the comments field below. Of course, if the work to implement this is beyond your abilities or the time available to you, please feel free to contact us and we’ll contract to do the work for you.

Free Webcast: Email Security and Archiving in the Cloud

Interested in outsourcing your email services but are afraid of what affect this might have on  your corporate mandate (can you say “Sar-Box”) to retain copies of email and to do so securely? Well, Google has announced a webinar with a live Q&A session to be held on Tuesday June 9, 2009 at 9am PDT (12 noon EDT/17:00 GMT).

You can learn:

  • How to take advantage of cloud solutions today to better your business and save money!
  • How cloud computing can provide you with an affordable and secure solution for archiving business emails
  • Why email security in the cloud is more effective than the running email in house (in most cases)

And best yet, if you register for this free webcast, even if you can’t make it, you’ll be sent a copy of the recording for later viewing. Or better yet, when you get the link, you can share with those around you; perhaps event that stake holder that has been preventing you from moving forward with moving your business’ email into the cloud!

Register for free email security and archiving webinar.

Enhancing your ASPDotNetStorefront Search Page

Enhanced Search Page for AspDotNetStoreFront I recently completed a search page upgrade on one of my client websites (http://www.tobacco-barn.com) and was pleased enough with some of the code on this that I thought I’d share it with the community. Our goals were as follows:

  1. Limit search to just show products and not each variant of the a product
  2. Include images with the search results
  3. Include a description (no more than 500 characters) with each search result
  4. Try and maintain all changes within the page.search.xml.config file

[more]

Of course the first step is to copy the original xml.config file from the /XmlPackages folder into the XmlPackages folder under the skin we are working on.

The next step was to exclude multiple variations (variants) of a product from showing on the result page. At first I figured that I would set up the Product template to ignore the variants after the first one. Then I stumbled on a post on the ASPDNSF support forums indicating that by changing the value of the @ViewType parameter from 0 to 1, I could signal to the stored procedure to only return the product information for a product using the default variant.

The next step was similarly easy to accomplish. After adding another column to the table holding the Product Results (found almost at the end of the / (root) template), i inserted the following lines of code into the Product template:

<td valign="middle" align="left"><a href="{aspdnsf:ProductLink(ProductID, SEName, 0, '')}"><xsl:value-of select="aspdnsf:LookupProductImage(ProductID, ImageFileNameOverride, SKU, 'icon', 0)" disable-output-escaping="yes" /></a></td>

Next up is to get the description to include in the search results listing. First try was to apply substring() to the results from description to just truncate them. The challenge is that if you truncate the product description and the description contains HTML tags, you might accidently split the tags and cause display problems for the remainder of the page. So, I stumbled on some XSTL code that will remove the HTML tags from the content.

So, at the top of the Product template, we create a param and store the Description value that has been transformed by the removeTags template.

<xsl:param name="pDescription"><xsl:call-template name="removeTags"><xsl:with-param name="field" select="Description"/></xsl:call-template></xsl:param>

and the following code gets added to the cell that contains the product name. It checks the length of Description and truncates it if necessary.

<br /><xsl:if test="string-length($pDescription) &gt; 500"><xsl:value-of select="substring($pDescription,0,497)" disable-output-escaping="yes" />...</xsl:if><xsl:if test="string-length($pDescription) &lt;= 500"><xsl:value-of select="$pDescription" disable-output-escaping="yes" /></xsl:if>

Of course all of this is dependant upon the following template to strip out the HTML tags:

<xsl:template name="removeTags"><xsl:param name="field"/><xsl:choose><xsl:when test="contains($field, '&lt;') and contains(substring-after($field, '&lt;'), '>')"><xsl:value-of select="substring-before($field, '&lt;')"/><xsl:call-template name="removeTags"><xsl:with-param name="field" select="substring-after(substring-after($field, '&lt;'), '>')"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:value-of select="$field"/></xsl:otherwise></xsl:choose></xsl:template>

Hopefully you’ll find this code useful. If you have similar code that has some improvements to it, please feel free to use the comments
section below to give us our opinion on this solution.

Recursing Through AppConfig File

While doing some updates to the EmmCLA program (more to come on this soon), I needed to have it loop through all the AppSettings in in App.Config file (the same should hold true for Web.Config for web apps) to find all occurrences of appsettings that were similar to a certain string.

A few Google searches later led me to the solution of using System.Configuration.ConfigurationSettings.AppSettings.AllKeys which returns a string array of all the keys in the AppSettings portion of App.Config:

// Loop through all AppSetting keys to find those 
// matching DBConn-xxxx
string[] AppSettings = ConfigurationSettings.AppSettings.AllKeys;foreach (string s in AppSettings){if (s.ToLower().Contains("dbconn-")){
// Do Something Here
}}

I’ve posted this in case anyone else finds a need to do something similar. This saved me a great deal of work and hopefully someone else will similarly benefit.

If you find this of some benefit, please leave us a comment below and let us know how you are using it.

Webgains, ASPDotnetStorefront and Google Checkout, Oh My!

I got a Google Alert about an article posted recently by UK Developers over at WebOpius. The put together a nice little piece about how to get all three of these technologies up and running, and better yet, playing nicely together. This is the first of many posts by them on this subject. I very much look forward to seeing how the progress on this project as it may prove beneficial to my customers as well!

In case you aren’t familiar, ASPDotNetStorefront (ASPDNSF) is the leading e-commerce solution for the ASP.NET platform. Google Checkout is a competitor (of sorts) to PayPal while WebGains is an affiliate facilitator where merchants can create and manage an affiliate network to help sell more.

Some of you may be saying, but wait, doesn’t ASPDNSF have an affiliate program built in? Yes Virginia, it does. However, it is really more of a framework upon which to build your own affiliate program. Not only will an affiliate program like WebGains help you manage your relationship with your affiliates, but you will also have access to a ready market of engaged affiliates rather than having to drum them up and vet them yourself.

Here’s a link to the original article: http://www.webopius.com/content/249/integrating-webgains-affiliate-network-with-aspdotnetstorefront/

Do you have experience working with affiliates with your e-commerce platform? If so, please feel free to share your experiences, good and bad!