Wednesday, October 23, 2013

Small Retailers as a Market for Tech Startups

Last week, ET published an article on how small and medium retailers wanting to take their business online are turning to technology startups for help. These typically charge Rs 1,000 to Rs 4,000 a month for technology services ranging from building websites to linking them with payment gateways and logistics providers. When compared to the potential earnings from doing big projects for large customers, these amounts are negligible. Still some of these companies are confident of being profitable soon. This got me thinking on how it makes business sense for these startups to target retailers as a market for cloud-based services. To be profitable with this model they would need huge volumes, meaning a large number of retailers. But are Indian retailers ready to take the Web plunge?

Let's look at it from a retailer's point of view. Here shall assume that the retailer in question is not just a grocer or a hardware store owner. He/she has one or more specialized products or services and seeks to target a particular segment of customers. Consider an exercise equipment shop, for example. For such an entrepreneur, normal Above The Line advertising alone will not bring in customers. Nor will word of mouth publicity get them the large number of leads they require, given their low conversion ratio of leads to sales. Since theirs is a lifestyle product, they would need to reach out to their target audience through micro level focused messaging. An online presence, including social media outreach, would be an essential part of their strategy. Here's where a tech startup can help.

Social media advertising and reviews on popular forums can attract the customer's attention to either the physical shop (where it is arguably easier to close a sale) or at least a website. If the website is designed and built well, and has payment gateway integration, it is possible to push the customer into buying the product online itself, while a tie-up with a logistics provider ensures that the product is delivered to the customer's house within an acceptable timeline. If the customer can be coaxed into writing a Web review of the product, that in turn would bring in more leads for the entrepreneur. On seeing that all these services are available for a moderate monthly payment, other retailers would jump on the bandwagon. So it's a  win-win situation for the entrepreneurs as well as the tech startup.

Tuesday, October 22, 2013

Object-Oriented Programming in Perl

My first and last brush with Perl OO programming was back in 2008. I was in the Netherlands with a couple of colleagues, getting "KT" for a set of small e-commerce applications whose support was being outsourced to India. We were horrified to see that the code was object-oriented, with many layers of inheritance, which made it extremely difficult to learn. As part of the Knowledge Transfer, we were asked to create installers and use them to get the applications running on a new server. But we would inevitably run into errors, which would send us hunting from file to file and class to class to try and find the ultimate parent class. Even the Dutch team that had been supporting the code for a few years did not know the nitty-gritty of the inheritance - they  had only learnt enough to support the applications on a day to day basis.

Having learnt C++ and Java earlier, I had realized then that Perl is not the best language for object-oriented programming. But the fact that it supports OO means that you need to know the basics, just in case you face a situation like I did. There are many online tutorials available on the subject but the best ones come straight from the horse's mouth, viz: the perlootut tutorial and  the perlobj language reference. After going through these, you may feel confident enough to create your own class and then test it with a simple script. I first created a very basic class called Muzak to represent the songs from my music collection. Each Muzak object has up to 4 attributes - a song name (mandatory), artist name, album title and year. It has 1 method - artist() - that returns the artist name. I put the class in a Perl module called Muzak.

Muzak.pm

package Muzak;

# Constructor
sub new {
    my $class = shift;
    my ( $song, $artist, $album, $year ) = @_;
    
    if ($song eq "") {
        die "Muzak object requires at least Song Name attribute";
    }

    my $self = bless {
        song => $song,
        artist => $artist,
        album => $album,
        year => $year,
    }, $class;

    return $self;
}

# Method: Get artist
sub artist {
    my $self = shift;
    return $self->{artist};
}

1;

Note that the "1;" at the end of the .pm file is critical. If you miss it, the Perl interpreter will throw an error while testing the script, which would look like "Muzak.pm did not return a true value at test_muzak.pl line 6". Also note that the check for non-blank song name is also not mandatory to create a working class - it is just a logical check that I added.

test_muzak.pl

use Muzak;
use feature qw(say);

# Create new Muzak object with all 4 paramaters
my $muzak1 = Muzak->new('Aqualung', 'Jethro Tull', 'Aqualung', '1971');

# Print the song artist name
say "Artist1 is " . $muzak1->artist();

# Create new Muzak object with only 1 parameter
my $muzak2 = Muzak->new('Bouree');

# Try printing the song artist name
say "Artist2 is " . $muzak2->artist();

# Try creating new Muzak object with 0 parameters
my $muzak3 = Muzak->new();

# Try printing the song artist name
say "Artist3 is " . $muzak3->artist();

There's a lot more to explore in Perl OO programming. I can write code that is much more complicated, like those Dutch applications (which were created, if I remember correctly, by a UK firm). More importantly, I can write code that is more useful than just playing around with song details. But that's another day, another class, another blog post

Friday, October 18, 2013

Excel output from PHP script

Let's say you've written a PHP script that queries a data source (say a MySQL database) and displays the output in the browser. Now you want to export this data to an Excel sheet that the user can print or process further. What are the different ways of doing this?

The first way I ever learned was to simply set the PHP content type header, like "Content-type: application/vnd.ms-excel; name='excel'". This prompts the user to open or save an Excel sheet, which would contain our tabular content. But in this method, you would not have any control over the formatting of the Excel sheet, such as borders, fonts, colors, etc.

If you want to generate a well-formatted Excel sheet, you can use the PHP library called PHPExcel, which can be downloaded from here. Just copy part of the zip file contents (see the "install.txt" file) to a sub-directory on your web server document root and you can get going. It is easy to save your tabular content to an Excel file on the server, using PHPExcel.

The code required for creating the Excel file is fairly simple, and you can put it together by looking at the examples given in the PHPExcel zip file. If you get stuck, say on a formatting issue, you can always google the solution. PHPExcel seems to be quite popular and so, more likely than not, your question would have been answered on one of the coding forums.

Here is my code for saving my Music Database List content as an Excel file:

/* Include PHPExcel */
require_once '../../Classes/PHPExcel.php';

// Create new PHPExcel object
$objPHPExcel = new PHPExcel();

// Set document properties
$objPHPExcel->getProperties()->setCreator("Ajay Ramakrishnan")
    ->setLastModifiedBy("Ajay Ramakrishnan")
    ->setTitle("Music Database List")
    ->setSubject("Music Database List")
    ->setDescription("Music Database List, generated using PHPExcel.")
    ->setKeywords("Music Database PHPExcel")
    ->setCategory("Music Database List");

// Add title row to Excel file
$objPHPExcel->setActiveSheetIndex(0)
    ->setCellValue('A1', $a[0])
    ->setCellValue('B1', $b[0])
    ->setCellValue('C1', $c[0])
    ->setCellValue('D1', $d[0]);

// Set the title row font to bold and background color to light slate grey
$header_range = "A1:D1";
$objPHPExcel->getActiveSheet()->getStyle($header_range)->getFont()->setBold(true);
$bgColorArray = array(
                    'fill' => array(
                        'type' => PHPExcel_Style_Fill::FILL_SOLID,
                        'color' => array('rgb' => '6D7B8D')
                    )
                );
$objPHPExcel->getActiveSheet()->getStyle($header_range)->applyFromArray($bgColorArray);

// Loop through the existing data rows
for ($i=2; $i <= $row_count; $i++) {
    $objPHPExcel->setActiveSheetIndex(0)
        ->setCellValue('A' . $i, $a[$i-1])
        ->setCellValue('B' . $i, $b[$i-1])
        ->setCellValue('C' . $i, $c[$i-1])
        ->setCellValue('D' . $i, $d[$i-1]);
    }

// Resize the columns
$objPHPExcel->getActiveSheet()->getColumnDimension('A')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('C')->setAutoSize(true);
$objPHPExcel->getActiveSheet()->getColumnDimension('D')->setAutoSize(true);

// Set the border for all the non-empty cells
$i = $i - 1;
$styleArray = array(
        'borders' => array(
            'left' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'right' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'top' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
            'bottom' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
            ),
        ),
    );
$objPHPExcel->getActiveSheet()->getStyle('A1:D' . $i)->applyFromArray($styleArray, False);

// Rename worksheet
$objPHPExcel->getActiveSheet()->setTitle('Music_DB_List');

// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$objPHPExcel->setActiveSheetIndex(0);

// Save Excel 2007 file
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save(str_replace('.php', '.xlsx', __FILE__));

Friday, October 4, 2013

Parsing HTML pages using Mojo::DOM

After my previous post, I successfully wrote a Perl script to parse an XML file that I had retrieved (from an RSS feed) using Perl and cURL. XML parsing and manipulation is simple enough, if you use the XML::Simple module. But what if the web page you are retrieving with Perl and cURL is an HTML page? And what if you have to make some changes to the HTML code before you render it in your browser? This would require a module that allows you to access individual DOM elements and even modify them. That is how I learned about the Mojo::DOM module, which is part of a package called Mojolicious that you can get on CPAN. Mojolicious calls itself "a next generation web framework for the Perl programming language". You can learn more on their website. Installing it on your machine is simple enough, using the command:

ppm install Mojolicious

Meanwhile, I decided to retrieve a particular web site's home page, make a couple of changes in the code, and render the same page in my browser. The changes were: 1) I would remove their Google analytics code, which was enclosed in a <script> tag pair, and (2) I would ensure that all references to stylesheets and images are prefixed with the URL of that particular web site, so that the web page in my browser appears identical to the original. Here are some of the interesting things that I learned about Mojo::DOM while completing this script, explained usingcode snippets:

$dom = Mojo::DOM->new->xml(0)->parse($response_body);

* Here I have created a new Mojo::DOM object, by parsing the response from my cURL call. The xml(0) is to tell Mojo::DOM to use HTML mode instead of XML mode

my @links = $domref->find('[href]')->each;

* Here I am telling Mojo::DOM to return all HTML tags having a 'href' attribute. I can then go through the @links array using foreach()

$_->attr(href => $linkhref);

* Here I am replacing the value of the 'href' attribute of a particular tag to a string $linkhref, which is actually a modified version of the original value

$_->replace_content($styletext);

* Here I am replacing the entire contents of a particular <style> tag pair with a modified version of the original contents. Interestingly the replace_content function has a bug - it replaces all instances of double quotes with the HTML entity code equivalent '&quot;', which may cause problems in the HTML output. So you need to change the HTML entity code back to double quotes before the end of the script

say "$domref";

* Here I am outputting the modified HTML code to the browser. For those who are not aware, say is the Perl equivalent of Java's println. It saves you the trouble of appending a "\n" at the end of every print statement. Using say requires the line "use feature qw(say);" along with your module declarations