<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Python Excels &#187; Python</title>
	<atom:link href="http://www.pythonexcels.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pythonexcels.com</link>
	<description>Data Mining with Excel and Python</description>
	<lastBuildDate>Mon, 08 Feb 2010 03:56:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Extending Pivot Table Data</title>
		<link>http://www.pythonexcels.com/2009/12/extending-pivot-table-data/</link>
		<comments>http://www.pythonexcels.com/2009/12/extending-pivot-table-data/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 19:20:17 +0000</pubDate>
		<dc:creator>dan</dc:creator>
				<category><![CDATA[ERP]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=248</guid>
		<description><![CDATA[As shown in the last post, automating pivot table generation with Python and Excel helps you quickly clean up a spreadsheet, organize data and build useful reports in very few lines of code.  Another useful data preparation technique is to build new columns of information based on the available data.  For example, you [...]]]></description>
			<content:encoded><![CDATA[<p>As shown in the <a href="http://www.pythonexcels.com/2009/11/automating-pivot-tables-with-python/">last post</a>, automating pivot table generation with Python and Excel helps you quickly clean up a spreadsheet, organize data and build useful reports in very few lines of code.  Another useful data preparation technique is to build new columns of information based on the available data.  For example, you could add an industry segment column to group company names by industry, or add an item type column to group sales items by category.  While Excel does have some functions to help with adding new data fields, automation with Python eliminates the tedium of clicking column names and entering formulas.</p>
<p>Excel does provide a function for calculating new values within a pivot table.  One example is extending a pivot table containing pricing and quantity data to compute an average selling price.  For example, given the table below:</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_salesbyqtr.png" alt="20091203_salesbyqtr" title="20091203_salesbyqtr" width="392" height="323" class="alignnone size-full wp-image-249" /></p>
<p>a new label called &#8220;ASP&#8221;, which is the Net Booking divided by the Quantity, can be added quickly and easily with Excel&#8217;s Calculated Field capability.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_calcfield.png" alt="20091203_calcfield" title="20091203_calcfield" width="549" height="612" class="alignnone size-full wp-image-250" /></p>
<p>This feature is handy for adding labels on the fly that require a simple calculation.  </p>
<p>In other cases, deriving the new field may not be so simple, yet needs to be performed each time the spreadsheet is updated.  Python can programmatically add new data fields to the source table so that the data is ready for viewing whenever the pivot table is opened.</p>
<p>The script developed last time automated the data cleanup and pivot table generation tasks.  Doing some further analysis based on the output spreadsheet, I created a chart of the Top 10 Customers for ABCD Catering: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_top10chart.png" alt="20091203_top10chart" title="20091203_top10chart" width="550" height="353" class="alignnone size-full wp-image-251" /></p>
<p>Note that some of the company names are 15 characters or longer in length and occupy much of the chart space.  It would be nice to have a shorter &#8220;nickname&#8221; for each company that could be used in the charts.  One solution is to cut and paste the pivot table data, then modify the Company Name information by hand.  Unfortunately, this would be very tedious.  Another approach is to automate the process in the script and create a new column derived from a comprehensive reference table of company names and nicknames.  The downside is that maintaining the list could be an issue as the business grows and the list of customers grows longer.  A third method is to create an algorithm that uses the first word in the company name wherever possible, and uses a defined nickname for other special cases.  &#8220;Sun Microsystems&#8221; becomes &#8220;Sun&#8221; and &#8220;Cisco Systems&#8221; becomes &#8220;Cisco&#8221;, while other company names such as &#8220;Hewlett-Packard&#8221; could be listed in a lookup with a nickname such as &#8220;HP&#8221;.  The snippet below shows how this is done.</p>
<pre class="brush: python;">
logolookup = {'Applied Materials':'AMAT', 'Electronic Arts':'EA',
              'Hewlett-Packard':'HP', 'KLA-Tencor':'KLA'}
if (&quot;Company Name&quot; in newdata[0]):
    cindx = newdata[0].index(&quot;Company Name&quot;)
    newdata[0][cindx+1:cindx+1] = [&quot;Logo Name&quot;]
    for rcnt in range(1,len(newdata)):
        if newdata[rcnt][cindx] in logolookup:
            newdata[rcnt][cindx+1:cindx+1] = [logolookup[newdata[rcnt][cindx]]]
        else:
            newname = newdata[rcnt][cindx].split()[0]
            newdata[rcnt][cindx+1:cindx+1] = [newname]
            logolookup[newdata[rcnt][cindx]] = newname
</pre>
<p>This code begins with  a simple lookup for company names and can be easily extended as special case company names are added.  Next, the column location of the &#8220;Company Name&#8221; field is identified and the new header &#8220;Logo Name&#8221; is inserted after &#8220;Company Name&#8221; in the list using the <code>list[index:index]</code> construct.  The <code>for</code> loop iterates over each row in the table, checking whether the company name for that row exists in the <code>logolookup</code> dictionary, then inserting the abbreviated name.  If not found, then the original company name is <code>split()</code> into words and the first word used as the new abbreviated name.  Finally, the <code>logolookup</code> dictionary is updated with the new abbreviated name.  </p>
<p>After running the program, the new column &#8220;Logo Name&#8221; has been inserted after &#8220;Company Name&#8221; and contains the shortened company names.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_withlogo.png" alt="20091203_withlogo" title="20091203_withlogo" width="431" height="273" class="alignnone size-full wp-image-252" /></p>
<p>The new &#8220;Logo Name&#8221; column can be used in the previous pivot table and chart, replacing the &#8220;Company Name&#8221; field and producing a cleaner chart with less area used for displaying company name information.<br />
<img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_top10wlogo.png" alt="20091203_top10wlogo" title="20091203_top10wlogo" width="550" height="354" class="alignnone size-full wp-image-253" /> </p>
<p>Another use of this technique is to add a label for &#8220;Food Category&#8221; based on the type of food purchased.  For example, the food items sold by ABCD Catering are: Caesar Salad, Cheese Pizza, Cheeseburger, Chocolate Sundae, Churro, Hamburger, Hot Dog, Pepperoni Pizza, Potato Chips and Soda.  Let&#8217;s say that your manager wants to track the sales of different food categories, such as Burger, Dessert, HotDog, Drink, Pizza, Salad and Snack.  Using the same technique outlined above, this code will add a column for Food Category with the appropriate entry for each food item: </p>
<pre class="brush: python;">
foodlookup = {'Caesar Salad':'Salad', 'Cheese Pizza':'Pizza',
              'Cheeseburger':'Burger', 'Chocolate Sundae':'Dessert',
              'Churro':'Snack', 'Hamburger':'Burger', 'Hot Dog':'HotDog',
              'Pepperoni Pizza':'Pizza', 'Potato Chips':'Snack',
              'Soda':'Drink'}
if (&quot;Food Name&quot; in newdata[0]):
    cindx = newdata[0].index(&quot;Food Name&quot;)
    newdata[0][cindx+1:cindx+1] = [&quot;Food Category&quot;]
    for rcnt in range(1,len(newdata)):
        if newdata[rcnt][cindx] in foodlookup:
            newdata[rcnt][cindx+1:cindx+1] = [foodlookup[newdata[rcnt][cindx]]]
        else:
            newdata[rcnt][cindx+1:cindx+1] = ['UNDEFINED']
</pre>
<p>If a food item is not found in the lookup, the category is labeled UNDEFINED.  This is an indication that there is a problem with the script and the lookup for food categories needs to be extended. </p>
<p>The section of the script which creates the pivot tables can be easily extended to build a new table based on the newly created label &#8220;Food Category&#8221;:</p>
<pre class="brush: python;">
# What food category had the highest unit sales in Q4?
ptname = addpivot(wb,src,
         title=&quot;Unit Sales by Food Category&quot;,
         filters=(&quot;Fiscal Quarter&quot;,),
         columns=(),
         rows=(&quot;Food Category&quot;,),
         sumvalue=&quot;Sum of Quantity&quot;,
         sortfield=(&quot;Food Category&quot;,win32c.xlDescending))
wb.Sheets(&quot;Unit Sales by Food Category&quot;).PivotTables(ptname).PivotFields(&quot;Fiscal Quarter&quot;).CurrentPage = &quot;2009-Q4&quot;
</pre>
<p>Based on the output spreadsheet, the best selling food category in Q4 based on quantity is &#8220;Snack&#8221;, with sales of 13700 units.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/12/20091203_foodcategory.png" alt="20091203_foodcategory" title="20091203_foodcategory" width="333" height="381" class="alignnone size-full wp-image-254" /></p>
<p>Here is the completed script, also available on <a href="http://github.com/pythonexcels/examples">GitHub</a></p>
<pre class="brush: python;">
#
# erppivotextended.py:
# Load raw EPR data, clean up header info,
# insert additional data fields and build 5 pivot tables
#
import win32com.client as win32
win32c = win32.constants
import sys
import itertools
tablecount = itertools.count(1)

def addpivot(wb,sourcedata,title,filters=(),columns=(),
             rows=(),sumvalue=(),sortfield=&quot;&quot;):
    &quot;&quot;&quot;Build a pivot table using the provided source location data
    and specified fields
    &quot;&quot;&quot;
    newsheet = wb.Sheets.Add()
    newsheet.Cells(1,1).Value = title
    newsheet.Cells(1,1).Font.Size = 16

    # Build the Pivot Table
    tname = &quot;PivotTable%d&quot;%tablecount.next()

    pc = wb.PivotCaches().Add(SourceType=win32c.xlDatabase,
                                 SourceData=sourcedata)
    pt = pc.CreatePivotTable(TableDestination=&quot;%s!R4C1&quot;%newsheet.Name,
                             TableName=tname,
                             DefaultVersion=win32c.xlPivotTableVersion10)
    wb.Sheets(newsheet.Name).Select()
    wb.Sheets(newsheet.Name).Cells(3,1).Select()
    for fieldlist,fieldc in ((filters,win32c.xlPageField),
                            (columns,win32c.xlColumnField),
                            (rows,win32c.xlRowField)):
        for i,val in enumerate(fieldlist):
            wb.ActiveSheet.PivotTables(tname).PivotFields(val).Orientation = fieldc
            wb.ActiveSheet.PivotTables(tname).PivotFields(val).Position = i+1

    wb.ActiveSheet.PivotTables(tname).AddDataField(
        wb.ActiveSheet.PivotTables(tname).PivotFields(sumvalue[7:]),
        sumvalue,
        win32c.xlSum)
    if len(sortfield) != 0:
        wb.ActiveSheet.PivotTables(tname).PivotFields(sortfield[0]).AutoSort(sortfield[1], sumvalue)
    newsheet.Name = title

    # Uncomment the next command to limit output file size, but make sure
    # to click Refresh Data on the PivotTable toolbar to update the table
    # newsheet.PivotTables(tname).SaveData = False

    return tname

def runexcel():
    &quot;&quot;&quot;Open the spreadsheet ABCDCatering.xls, clean it up,
    and add pivot tables
    &quot;&quot;&quot;
    excel = win32.gencache.EnsureDispatch('Excel.Application')
    #excel.Visible = True
    try:
        wb = excel.Workbooks.Open('ABCDCatering.xls')
    except:
        print &quot;Failed to open spreadsheet ABCDCatering.xls&quot;
        sys.exit(1)
    ws = wb.Sheets('Sheet1')
    xldata = ws.UsedRange.Value
    newdata = []
    for row in xldata:
        if len(row) == 13 and row[-1] is not None:
            newdata.append(list(row))
    lasthdr = &quot;Col A&quot;
    for i,field in enumerate(newdata[0]):
        if field is None:
            newdata[0][i] = lasthdr + &quot; Name&quot;
        else:
            lasthdr = newdata[0][i]

    logolookup = {'Applied Materials':'AMAT', 'Electronic Arts':'EA',
                  'Hewlett-Packard':'HP', 'KLA-Tencor':'KLA'}
    if (&quot;Company Name&quot; in newdata[0]):
        cindx = newdata[0].index(&quot;Company Name&quot;)
        newdata[0][cindx+1:cindx+1] = [&quot;Logo Name&quot;]
        for rcnt in range(1,len(newdata)):
            if newdata[rcnt][cindx] in logolookup:
                newdata[rcnt][cindx+1:cindx+1] = [logolookup[newdata[rcnt][cindx]]]
            else:
                newname = newdata[rcnt][cindx].split()[0]
                newdata[rcnt][cindx+1:cindx+1] = [newname]
                logolookup[newdata[rcnt][cindx]] = newname

    foodlookup = {'Caesar Salad':'Salad', 'Cheese Pizza':'Pizza',
                  'Cheeseburger':'Burger', 'Chocolate Sundae':'Dessert',
                  'Churro':'Snack', 'Hamburger':'Burger', 'Hot Dog':'HotDog',
                  'Pepperoni Pizza':'Pizza', 'Potato Chips':'Snack',
                  'Soda':'Drink'}
    if (&quot;Food Name&quot; in newdata[0]):
        cindx = newdata[0].index(&quot;Food Name&quot;)
        newdata[0][cindx+1:cindx+1] = [&quot;Food Category&quot;]
        for rcnt in range(1,len(newdata)):
            if newdata[rcnt][cindx] in foodlookup:
                newdata[rcnt][cindx+1:cindx+1] = [foodlookup[newdata[rcnt][cindx]]]
            else:
                newdata[rcnt][cindx+1:cindx+1] = ['UNDEFINED']

    rowcnt = len(newdata)
    colcnt = len(newdata[0])
    wsnew = wb.Sheets.Add()
    wsnew.Range(wsnew.Cells(1,1),wsnew.Cells(rowcnt,colcnt)).Value = newdata
    wsnew.Columns.AutoFit()

    src = &quot;%s!R1C1:R%dC%d&quot;%(wsnew.Name,rowcnt,colcnt)

    # What were the total sales in each of the last four quarters?
    addpivot(wb,src,
             title=&quot;Sales by Quarter&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Fiscal Quarter&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=())

    # What are the sales for each food item in each quarter?
    addpivot(wb,src,
             title=&quot;Sales by Food Item&quot;,
             filters=(),
             columns=(&quot;Food Name&quot;,),
             rows=(&quot;Fiscal Quarter&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=())

    # Who were the top 10 customers for ABCD Catering in 2009?
    addpivot(wb,src,
             title=&quot;Top 10 Customers&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Company Name&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=(&quot;Company Name&quot;,win32c.xlDescending))

    # Who was the highest producing sales rep for the year?
    addpivot(wb,src,
             title=&quot;Top Sales Reps&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Sales Rep Name&quot;,&quot;Company Name&quot;),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=(&quot;Sales Rep Name&quot;,win32c.xlDescending))

    # What food item had the highest unit sales in Q4?
    ptname = addpivot(wb,src,
             title=&quot;Unit Sales by Food&quot;,
             filters=(&quot;Fiscal Quarter&quot;,),
             columns=(),
             rows=(&quot;Food Name&quot;,),
             sumvalue=&quot;Sum of Quantity&quot;,
             sortfield=(&quot;Food Name&quot;,win32c.xlDescending))
    wb.Sheets(&quot;Unit Sales by Food&quot;).PivotTables(ptname).PivotFields(&quot;Fiscal Quarter&quot;).CurrentPage = &quot;2009-Q4&quot;

    # What food category had the highest unit sales in Q4?
    ptname = addpivot(wb,src,
             title=&quot;Unit Sales by Food Category&quot;,
             filters=(&quot;Fiscal Quarter&quot;,),
             columns=(),
             rows=(&quot;Food Category&quot;,),
             sumvalue=&quot;Sum of Quantity&quot;,
             sortfield=(&quot;Food Category&quot;,win32c.xlDescending))
    wb.Sheets(&quot;Unit Sales by Food Category&quot;).PivotTables(ptname).PivotFields(&quot;Fiscal Quarter&quot;).CurrentPage = &quot;2009-Q4&quot;

    if int(float(excel.Version)) &gt;= 12:
        wb.SaveAs('newABCDCatering.xlsx',win32c.xlOpenXMLWorkbook)
    else:
        wb.SaveAs('newABCDCatering.xls')
    excel.Application.Quit()

if __name__ == &quot;__main__&quot;:
    runexcel()
</pre>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program erppivotextended.py and spreadsheet file ABCDCatering.xls are available at<br /><a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>Thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/12/extending-pivot-table-data/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Automating Pivot Tables with Python</title>
		<link>http://www.pythonexcels.com/2009/11/automating-pivot-tables-with-python/</link>
		<comments>http://www.pythonexcels.com/2009/11/automating-pivot-tables-with-python/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 03:49:01 +0000</pubDate>
		<dc:creator>dan</dc:creator>
				<category><![CDATA[ERP]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=237</guid>
		<description><![CDATA[In the last post I explained the basic concept behind Pivot Tables and provided some examples.  Pivot tables are an easy-to-use tool to derive some basic business intelligence from your data.  As discussed last time, there are occasions when you&#8217;ll need to do interactive data mining by changing column and row fields.  [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.pythonexcels.com/2009/11/introducing-pivot-tables">last post</a> I explained the basic concept behind Pivot Tables and provided some examples.  Pivot tables are an easy-to-use tool to derive some basic business intelligence from your data.  As discussed last time, there are occasions when you&#8217;ll need to do interactive data mining by changing column and row fields.  But in my experience, it&#8217;s handy to have my favorite reports built automatically, with the reports ready to go as soon as I open the spreadsheet.  In this post I&#8217;ll develop and explain the code to create a set of pivot tables automatically in worksheet. </p>
<p>The goal of this exercise is to automate the generation of pivot tables from the last post, and save them to a new Excel file.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/11/20091123_reports.png" alt="20091123_reports" title="20091123_reports" width="550" height="655" class="alignnone size-full wp-image-242" /></p>
<p>I started with the file <code>newABCDCatering.xls</code> from the previous post and record the macro to create this simple pivot table showing Net Bookings by Sales Rep and Food Name for the last four quarters.<br />
<img src="http://www.pythonexcels.com/wp-content/uploads/2009/11/20091123_setup.png" alt="20091123_setup" title="20091123_setup" width="550" height="396" class="alignnone size-full wp-image-238" /></p>
<p>Captured in Excel 2007, the recorded macro looks like this: </p>
<pre class="brush: vb;">
Sub Macro1()
'
' Macro1 Macro
'

'
    Selection.CurrentRegion.Select
    Sheets.Add
    ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
        &quot;Sheet2!R1C1:R791C13&quot;, Version:=xlPivotTableVersion10).CreatePivotTable _
        TableDestination:=&quot;Sheet3!R3C1&quot;, TableName:=&quot;PivotTable1&quot;, DefaultVersion _
        :=xlPivotTableVersion10
    Sheets(&quot;Sheet3&quot;).Select
    Cells(3, 1).Select
    With ActiveSheet.PivotTables(&quot;PivotTable1&quot;).PivotFields(&quot;Fiscal Year&quot;)
        .Orientation = xlPageField
        .Position = 1
    End With
    With ActiveSheet.PivotTables(&quot;PivotTable1&quot;).PivotFields(&quot;Fiscal Quarter&quot;)
        .Orientation = xlColumnField
        .Position = 1
    End With
    With ActiveSheet.PivotTables(&quot;PivotTable1&quot;).PivotFields(&quot;Sales Rep Name&quot;)
        .Orientation = xlRowField
        .Position = 1
    End With
    With ActiveSheet.PivotTables(&quot;PivotTable1&quot;).PivotFields(&quot;Food Name&quot;)
        .Orientation = xlRowField
        .Position = 2
    End With
    ActiveSheet.PivotTables(&quot;PivotTable1&quot;).AddDataField ActiveSheet.PivotTables( _
        &quot;PivotTable1&quot;).PivotFields(&quot;Net Booking&quot;), &quot;Sum of Net Booking&quot;, xlSum
End Sub
</pre>
<p>The post <a href="http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python/">Mapping Excel VB Macros to Python</a> covered a technique for recording a Visual Basic macro and porting it to Python.  Using that approach, you could simply turn on the macro recorder and generate all the required tables, producing a long script with lots of redundancy.  A better approach is to build a general purpose function that can be used over and over to generate the pivot tables.</p>
<p>Looking at the macro, you see lines specifying the <code>Orientation</code> of the field name, such as <code>.Orientation = xlRowField</code> and <code>.Orientation = xlColumnField</code>.  A pivot table has four basic areas for fields: </p>
<ul>
<li>Report Filter (<code>.Orientation = xlPageField</code>)</li>
<li>Column area (<code>.Orientation = xlColumnField</code>)</li>
<li>Row area (<code>.Orientation = xlRowField</code>)</li>
<li>Values area (<code>PivotTables().AddDataField()</code>)</li>
</ul>
<p>Each of these supports multiple fields (column fields for <code>Sales Rep Name</code> and <code>Food Name</code> were added in the example).  The ordering of the fields changes the appearance of the table.  </p>
<p>A general pattern should be apparent in this macro.  First, the pivot table is created with the <code>ActiveWorkbook.PivotCaches.Create()</code> statement.  Next, the columns and rows are configured with a series of <code>ActiveSheet.PivotTables("PivotTable1").PivotFields()</code> statements.  Finally, the field used in the <code>Values</code> section of the table is configured using the <code>ActiveSheet.PivotTables("PivotTable1").AddDataField</code> statement.  The general purpose function will need to contain all of these constructs.  Note the parts that can&#8217;t be hard-coded: the source of the data, <code>"Sheet2!R1C1:R791C13"</code>, and destination for the table, <code>"Sheet3!R3C1"</code> need to be determined based on the characteristics of the source data and can&#8217;t be hard coded in the general solution.</p>
<p>In Python, this pattern can be reduced to the following loop that covers fields for the Report Filter, Columns and Rows:</p>
<pre class="brush: python;">
def addpivot(wb,sourcedata,title,filters=(),columns=(),
             rows=(),sumvalue=(),sortfield=&quot;&quot;):
    &quot;&quot;&quot;Build a pivot table using the provided source location data
    and specified fields
    &quot;&quot;&quot;
    ...
    for fieldlist,fieldc in ((filters,win32c.xlPageField),
                            (columns,win32c.xlColumnField),
                            (rows,win32c.xlRowField)):
        for i,val in enumerate(fieldlist):
            wb.ActiveSheet.PivotTables(tname).PivotFields(val).Orientation = fieldc
        wb.ActiveSheet.PivotTables(tname).PivotFields(val).Position = i+1
    ...
</pre>
<p>Processing the Values field is more or less copied from the Visual Basic.  To keep things simple in this example, this code is limited to adding &#8220;Sum of&#8221; values only, and doesn&#8217;t handle other Summarize Value functions such as Count, Min, Max, etc.</p>
<pre class="brush: python;">
    wb.ActiveSheet.PivotTables(tname).AddDataField(
        wb.ActiveSheet.PivotTables(tname).PivotFields(sumvalue[7:]),
        sumvalue,
        win32c.xlSum)
</pre>
<p>The actual values for <code>filters</code>,<code>columns</code> and <code>rows</code> in the function are defined in the call to the function.  The complete function creates a new sheet within the workbook, then adds an empty pivot table to the sheet and builds the table using the field information provided.  For example, to answer the question: <i>What were the total sales in each of the last four quarters?</i>, the pivot table is built with the following call to the <code>addpivot</code> function:</p>
<pre class="brush: python;">
# What were the total sales in each of the last four quarters?
addpivot(wb,src,
         title=&quot;Sales by Quarter&quot;,
         filters=(),
         columns=(),
         rows=(&quot;Fiscal Quarter&quot;,),
         sumvalue=&quot;Sum of Net Booking&quot;,
         sortfield=())
</pre>
<p>which defines a pivot table using the row header &#8220;Fiscal Quarter&#8221; and data value &#8220;Sum of Net Booking&#8221;.  The title &#8220;Sales by Quarter&#8221; is used to name the sheet itself.</p>
<p>To make the output spreadsheet more understandable, the title parameter passed into the function and used as a title in each worksheet and as the tab name.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/11/20091123_titletabsbq.png" alt="20091123_titletabsbq" title="20091123_titletabsbq" width="389" height="363" class="alignnone size-full wp-image-243" /></p>
<p>The complete script is shown below.  Caveats:</p>
<ul>
<li>This script has been modified to run on both Excel 2007 and Excel 2003 and has been tested on those versions.</li>
<li>Adding pivot tables increases the size of the output Excel file, which can be mitigated by disabling caching of pivot table data.  Line 48 of the script contains the command <code>newsheet.PivotTables(tname).SaveData = False</code>, which has been commented out.  Uncommenting this command will reduce the size of the output Excel file, but will require that the pivot table be refreshed before use by clicking on Refresh Data on the PivotTable toolbar.</li>
</ul>
<pre class="brush: python;">
#
# erpdatapivot.py:
# Load raw EPR data, clean up header info and
# build 5 pivot tables
#
import win32com.client as win32
win32c = win32.constants
import sys
import itertools
tablecount = itertools.count(1)

def addpivot(wb,sourcedata,title,filters=(),columns=(),
             rows=(),sumvalue=(),sortfield=&quot;&quot;):
    &quot;&quot;&quot;Build a pivot table using the provided source location data
    and specified fields
    &quot;&quot;&quot;
    newsheet = wb.Sheets.Add()
    newsheet.Cells(1,1).Value = title
    newsheet.Cells(1,1).Font.Size = 16

    # Build the Pivot Table
    tname = &quot;PivotTable%d&quot;%tablecount.next()

    pc = wb.PivotCaches().Add(SourceType=win32c.xlDatabase,
                                 SourceData=sourcedata)
    pt = pc.CreatePivotTable(TableDestination=&quot;%s!R4C1&quot;%newsheet.Name,
                             TableName=tname,
                             DefaultVersion=win32c.xlPivotTableVersion10)
    wb.Sheets(newsheet.Name).Select()
    wb.Sheets(newsheet.Name).Cells(3,1).Select()
    for fieldlist,fieldc in ((filters,win32c.xlPageField),
                            (columns,win32c.xlColumnField),
                            (rows,win32c.xlRowField)):
        for i,val in enumerate(fieldlist):
            wb.ActiveSheet.PivotTables(tname).PivotFields(val).Orientation = fieldc
            wb.ActiveSheet.PivotTables(tname).PivotFields(val).Position = i+1

    wb.ActiveSheet.PivotTables(tname).AddDataField(
        wb.ActiveSheet.PivotTables(tname).PivotFields(sumvalue[7:]),
        sumvalue,
        win32c.xlSum)
    if len(sortfield) != 0:
        wb.ActiveSheet.PivotTables(tname).PivotFields(sortfield[0]).AutoSort(sortfield[1], sumvalue)
    newsheet.Name = title

    # Uncomment the next command to limit output file size, but make sure
    # to click Refresh Data on the PivotTable toolbar to update the table
    # newsheet.PivotTables(tname).SaveData = False

    return tname

def runexcel():
    excel = win32.gencache.EnsureDispatch('Excel.Application')
    #excel.Visible = True
    try:
        wb = excel.Workbooks.Open('ABCDCatering.xls')
    except:
        print &quot;Failed to open spreadsheet ABCDCatering.xls&quot;
        sys.exit(1)
    ws = wb.Sheets('Sheet1')
    xldata = ws.UsedRange.Value
    newdata = []
    for row in xldata:
        if len(row) == 13 and row[-1] is not None:
            newdata.append(list(row))
    lasthdr = &quot;Col A&quot;
    for i,field in enumerate(newdata[0]):
        if field is None:
            newdata[0][i] = lasthdr + &quot; Name&quot;
        else:
            lasthdr = newdata[0][i]
    rowcnt = len(newdata)
    colcnt = len(newdata[0])
    wsnew = wb.Sheets.Add()
    wsnew.Range(wsnew.Cells(1,1),wsnew.Cells(rowcnt,colcnt)).Value = newdata
    wsnew.Columns.AutoFit()

    src = &quot;%s!R1C1:R%dC%d&quot;%(wsnew.Name,rowcnt,colcnt)

    # What were the total sales in each of the last four quarters?
    addpivot(wb,src,
             title=&quot;Sales by Quarter&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Fiscal Quarter&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=())

    # What are the sales for each food item in each quarter?
    addpivot(wb,src,
             title=&quot;Sales by Food Item&quot;,
             filters=(),
             columns=(&quot;Food Name&quot;,),
             rows=(&quot;Fiscal Quarter&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=())

    # Who were the top 10 customers for ABCD Catering in 2009?
    addpivot(wb,src,
             title=&quot;Top 10 Customers&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Company Name&quot;,),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=(&quot;Company Name&quot;,win32c.xlDescending))

    # Who was the highest producing sales rep for the year?
    addpivot(wb,src,
             title=&quot;Top Sales Reps&quot;,
             filters=(),
             columns=(),
             rows=(&quot;Sales Rep Name&quot;,&quot;Company Name&quot;),
             sumvalue=&quot;Sum of Net Booking&quot;,
             sortfield=(&quot;Sales Rep Name&quot;,win32c.xlDescending))

    # What food item had the highest unit sales in Q4?
    ptname = addpivot(wb,src,
             title=&quot;Unit Sales by Food&quot;,
             filters=(&quot;Fiscal Quarter&quot;,),
             columns=(),
             rows=(&quot;Food Name&quot;,),
             sumvalue=&quot;Sum of Quantity&quot;,
             sortfield=(&quot;Food Name&quot;,win32c.xlDescending))
    wb.Sheets(&quot;Unit Sales by Food&quot;).PivotTables(ptname).PivotFields(&quot;Fiscal Quarter&quot;).CurrentPage = &quot;2009-Q4&quot;

    if int(float(excel.Version)) &gt;= 12:
        wb.SaveAs('newABCDCatering.xlsx',win32c.xlOpenXMLWorkbook)
    else:
        wb.SaveAs('newABCDCatering.xls')
    excel.Application.Quit()

if __name__ == &quot;__main__&quot;:
    runexcel()
</pre>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program erpdatapivot.py and input spreadsheet file ABCDCatering.xls are available at<br /><a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>Thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/11/automating-pivot-tables-with-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cleaning Up Corporate ERP Data</title>
		<link>http://www.pythonexcels.com/2009/11/cleaning-up-corporate-erp-data/</link>
		<comments>http://www.pythonexcels.com/2009/11/cleaning-up-corporate-erp-data/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 05:50:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ERP]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=191</guid>
		<description><![CDATA[The previous posts have used Excel and Python to create and manipulate small spreadsheets.  In reality, Python and Excel are especially well suited to tackling large data sets.  This post will illustrate some techniques for cleaning up data downloaded from corporate ERP systems such as SAP and Oracle, and getting it ready for some serious data mining with Excel.]]></description>
			<content:encoded><![CDATA[<p>The previous posts have used Excel and Python to create and manipulate small spreadsheets.  In reality, Python and Excel are especially well suited to tackling large data sets.  This post will illustrate some techniques for cleaning up data downloaded from corporate ERP systems such as SAP and Oracle, and getting it ready for some serious data mining with Excel.</p>
<p>In this example, a fictional company called ABCD Catering has recorded sales and order history for 2009 in their corporate ERP system.  ABCD Catering provides catering services to leading Silicon Valley companies, providing the best in hamburgers, hot dogs, churros, sodas and other comfort food.  Your boss has asked you to examine this data and answer some questions and produce charts representing some of the data:</p>
<ul>
<li>What were the total sales in each of the last four quarters?</li>
<li>What are the sales for each food item in each quarter?</li>
<li>Who were the top 10 customers for ABCD catering in Q1?</li>
<li>Who was the highest producing sales rep for the year?</li>
<li>What food item had the highest unit sales in Q4?</li>
</ul>
<p>Generating this information typically involves running five separate reports in the system.  Since your boss is looking for this same information at the end of each quarter, you want to simplify your life and your bosses by automating the report.  Using Python and Excel, you can download a spreadsheet copy of the raw data, process it, generate the key figures and charts and save them to a spreadsheet.</p>
<p>Take a look at the data in ABCDCatering.xls:</p>
<p><img class="alignnone size-full wp-image-192" title="20091102_original" src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091102_original.png" alt="20091102_original" width="550" height="255" /></p>
<p>The spreadsheet contains some header information, then a large table of records for each order.  Each record contains the fiscal year and quarter, food item, company name, order data, sales representative, booking and order quantity for each order.  The data needs some work before you can use it in a pivot table.  First, the data in rows 1 through 11 must be ignored, it&#8217;s meaningless for the pivot table.  Also, some columns do not have a proper header and must be corrected before the data can be used.  The good news is that after some minor massaging, this data will be ideally suited for processing with a pivot table in Excel.  Close the spreadsheet and get ready to build the reports.</p>
<p>The program begins with the standard boilerplate: import the win32 module and start Excel.  If you have questions on this, please refer to the <a href="http://www.pythonexcels.com/2009/09/basic-excel-driving-with-python">earlier</a> <a href="http://www.pythonexcels.com/2009/10/python-excel-mini-cookbook">posts</a>.</p>
<pre class="brush: python;">
#
# erpdata.py: Load raw EPR data and clean up header info
#
import win32com.client as win32
import sys
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True
</pre>
<p>Next, open the spreadsheet ABCDCatering.xls with some exception handling.  The <code>try/except</code> clause attempts to open the file with the <code>Workbooks.Open()</code> method, and exits gracefully if the file is missing or some other problem occurred.  Lastly, the variable <code>ws</code> is set to the spreadsheet containing the data.</p>
<pre class="brush: python; first-line: 8">
try:
    wb = excel.Workbooks.Open('ABCDCatering.xls')
except:
    print "Failed to open spreadsheet ABCDCatering.xls"
    sys.exit(1)
ws = wb.Sheets('Sheet1')
</pre>
<p>An easy way to load the entire spreadsheet into Python is the <code>UsedRange</code> method.  The following command:</p>
<pre class="brush: python; first-line: 14">
xldata = ws.UsedRange.Value
</pre>
<p>grabs all the data in the Sheet1 worksheet and copies it into a tuple named <code>xldata</code>.  Once inside Python, the data can be manipulated and placed back into the spreadsheet with minimal calls to the COM interface, resulting in faster, more efficient processing.</p>
<p>To delete rows, add columns and do other operations on the data, it must be converted to or copied to a list.  The approach used here is to examine the data row by row, discarding the non essential header rows and copying everything else to a new list.  The first step is to remove the rows that are not part of the column header row or record data.  If you are using Python to generate the program interactively, you can investigate the data in the <code>xldata</code> tuple and display the data for the first record (<code>xldata[0]</code>) and header record (<code>xldata[11]</code>):</p>
<p><img class="alignnone size-full wp-image-193" title="20091102_xldata0" src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091102_xldata0.png" alt="20091102_xldata0" width="570" height="132" /></p>
<p>The length of both rows is 13, though <code>xldata[0]</code> contains many elements with a value of <code>None</code>.  The following code checks the length of the data and skips any rows shorter then 13 fields or rows that contain <code>None</code> in the last field.  Note that this code assumes that the actual data in the table always contains complete records, true in this dataset but you should always understand the characteristics of the data you&#8217;re working on.</p>
<pre class="brush: python; first-line: 15">
newdata = []
for row in xldata:
    if row[-1] is not None and len(row) == 13:
        newdata.append(row)
</pre>
<p>The <code>newdata</code> list now contains the header and data rows from the spreadsheet, but the header row is still not complete.  All column headers must contain text in order to use this data in a pivot table.  Unfortunately, the spreadsheet downloads produced by the ERP system have the column label over the numberical identifier for the item, while the text column header is blank.  You can see that for the &#8220;Food&#8221; and &#8220;Company&#8221; data below.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091102_foodcompany.png" alt="20091102_foodcompany" title="20091102_foodcompany" width="454" height="216" class="alignnone size-full wp-image-194" /></p>
<p>One approach that works for this data is to scan the header and insert a column header based on the contents of the previous column.  For example, the label for column F could be &#8220;Company Name&#8221;, created by simply appending the text &#8221; Name&#8221; to the column header &#8220;Company&#8221; from the prior column.  Using this simple algorithm, the column header row can be filled out and the spreadsheet made ready for pivot table conversion.  A more complex lookup could be used as well, but the simple algorithm described here will scale if new fields are added to the report.</p>
<pre class="brush: python; first-line: 19">lasthdr = "Col A"
for i,field in enumerate(newdata[0]):
  if field is None:
    newdata[0][i] = lasthdr + " Name"
  else:
    lasthdr = newdata[0][i]
</pre>
<p>Now the data is ready for insertion back into the spreadsheet.  To enable comparison between the new data set and the original, create a new sheet in the workbook, write the data to the new sheet and autofit the columns.</p>
<pre class="brush: python; first-line: 25">
wsnew = wb.Sheets.Add()
wsnew.Range(wsnew.Cells(1,1),wsnew.Cells(len(newdata),len(newdata[0]))).Value = newdata
wsnew.Columns.AutoFit()
</pre>
<p>The last step is to save the worksheet to a new file and quit Excel.  The Excel version is checked in order to save the data in the correct spreadsheet format.  Version 12 corresponds to Excel 2007, which uses the <code>.xlsx</code> file extension.  You also have to specify the constant <code>xlOpenXMLWorkbook</code> to define the type of output Excel file. Earlier version of Excel use the <code>.xls</code> extension, and because the input file was .xls format, no output format specifier is needed for users of older versions of Excel.</p>
<pre class="brush: python; first-line: 28">
if int(float(excel.Version)) >= 12:
    wb.SaveAs('newABCDCatering.xlsx',win32.constants.xlOpenXMLWorkbook)
else:
    wb.SaveAs('newABCDCatering.xls')
excel.Application.Quit()
</pre>
<p>If the file <code>newABCDCatering.xlsx</code> or <code>newABCDCatering.xls</code> already exists in My Documents, you will see the following popup when you run the script.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091102_existspopup.png" alt="20091102_existspopup" title="20091102_existspopup" width="525" height="125" class="alignnone size-full wp-image-195" /></p>
<p>Click &#8220;Yes&#8221; to overwrite the spreadsheet file.   To run the script cleanly, erase the file <code>newABCDCatering.xlsx</code> or <code>newABCDCatering.xls</code> and try the script again.</p>
<p>After running the script, open the file newABCDCatering.xlsx or newABCDCatering.xls and view the contents.  Note that the extraneous header information has been removed and blank column header information has been inserted programmatically as described earlier.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091102_exceloutput.png" alt="20091102_exceloutput" title="20091102_exceloutput" width="588" height="228" class="alignnone size-full wp-image-196" /></p>
<p>The new spreadsheet is ready for use in a pivot table, which will be covered in the next post.   Here is the complete script, also available at <a href="http://github.com/pythonexcels/examples">github</a>.</p>
<pre class="brush: python;">
#
# erpdata.py: Load raw EPR data and clean up header info
#
import win32com.client as win32
import sys
excel = win32.gencache.EnsureDispatch('Excel.Application')
#excel.Visible = True
try:
    wb = excel.Workbooks.Open('ABCDCatering.xls')
except:
    print &quot;Failed to open spreadsheet ABCDCatering.xls&quot;
    sys.exit(1)
ws = wb.Sheets('Sheet1')
xldata = ws.UsedRange.Value
newdata = []
for row in xldata:
    if len(row) == 13 and row[-1] is not None:
        newdata.append(list(row))
lasthdr = &quot;Col A&quot;
for i,field in enumerate(newdata[0]):
    if field is None:
        newdata[0][i] = lasthdr + &quot; Name&quot;
    else:
        lasthdr = newdata[0][i]
wsnew = wb.Sheets.Add()
wsnew.Range(wsnew.Cells(1,1),wsnew.Cells(len(newdata),len(newdata[0]))).Value = newdata
wsnew.Columns.AutoFit()
if int(float(excel.Version)) &gt;= 12:
    wb.SaveAs('newABCDCatering.xlsx',win32.constants.xlOpenXMLWorkbook)
else:
    wb.SaveAs('newABCDCatering.xls')
excel.Application.Quit()
</pre>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program erpdata.py and spreadsheet file ABCDCatering.xls are available at<br />
<a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>Thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/11/cleaning-up-corporate-erp-data/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mapping Excel VB Macros to Python Revisited</title>
		<link>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python-revisited/</link>
		<comments>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python-revisited/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 07:01:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Excel]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=169</guid>
		<description><![CDATA[The last post introduced a technique for recording a Visual Basic macro within Excel and migrating it to Python.  This exercise will build on those techniques while leveraging Python for more of the work.  
This example creates two tables from scratch &#8212;  a simple multiplication table and a table of random numbers [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python">last post</a> introduced a technique for recording a Visual Basic macro within Excel and migrating it to Python.  This exercise will build on those techniques while leveraging Python for more of the work.  </p>
<p>This example creates two tables from scratch &#8212;  a simple multiplication table and a table of random numbers &#8212;  and applies conditional formatting to the numbers using some of the new features in Excel 2007 (unfortunately this exercise won&#8217;t be compatible with older versions of Excel).  Begin by starting the Python IDLE interface.  Next, start Excel as you&#8217;ve done in the previous exercises.  For this exercise, add a workbook using the <code>Workbooks.Add()</code> construct, and set the <code>ws</code> variable to point to the first worksheet in the workbook.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_startexcelidle.png" alt="20091019_startexcelidle" title="20091019_startexcelidle" width="550" height="100" class="alignnone size-full wp-image-170" /></p>
<p>After typing these command in IDLE, you&#8217;ll see the Excel window containing an empty spreadsheet.   To build the multiplication table, use Python to populate the column and row headers.  There are a number of ways to do this, for this exercise you&#8217;ll pass an list of column header and row header values to Excel.  A row of data is defined by using the <code>ws.Range().Value</code> statement with a list or tuple on right hand side of the equals sign.  Rather than explicitly defining the list as <code>[1,2,3,4,5,6,7,8,9,10]</code>, you can use a functional programming statement containing a <code>range()</code> statement to populate the values: <code>[i for i in range(1,11)]</code>. The complete statement is <code>ws.Range("B2:K2").Value = [i for i in range(1,11)]</code>.  Defining a single column of data is a bit trickier, you must define a list of single element lists or tuples.  One way to do this is to use Python&#8217;s <code>zip()</code> function to transpose the flat list into a list of tuples.  The complete statement is <code>ws.Range("B2:B11").Value = zip([i for i in range(1,11)])</code>.  The statements for completing the column and row headers are shown below. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_headers.png" alt="20091019_headers" title="20091019_headers" width="550" height="50" class="alignnone size-full wp-image-171" /></p>
<p>At this point the column and row headers will appear in the Excel spreadsheet.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_headersexcel1.png" alt="20091019_headersexcel" title="20091019_headersexcel" width="550" height="261" class="alignnone size-full wp-image-184" /></p>
<p>To define the product values for each cell in the table, create a formula to multiply the column and row header for a single cell, then used Excel to autofill the remaining cells.  Looking at the spreadsheet, the product for cell C3 is cell B3 multiplied by cell C2, or 2 times 2 which equals 4.  In terms of Excel, the formula is <code>=B3*C2</code>.  To use Excel&#8217;s autofill capability, you need to anchor the row and column in the formula by preceding it with the <code>$</code> character.  In other words, the formula you want to use is <code>=$B3*C$2</code>.   Once that formula is entered, the expansion to fill the remaining cells is done in two steps.  First, programmatically select the cell and drag it fill the row.  Next, select the newly autofilled row and drag the new row down to fill in the remaining rows.  Since this was demonstrated in the <a href="http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python">last post</a>, please refer to that post if you need more information.  The equivalent Python code to implement the autofill is shown below.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_autofill.png" alt="20091019_autofill" title="20091019_autofill" width="550" height="137" class="alignnone size-full wp-image-173" /></p>
<p>The spreadsheet will now contain the complete multiplication table.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_autofillexcel.png" alt="20091019_autofillexcel" title="20091019_autofillexcel" width="550" height="271" class="alignnone size-full wp-image-174" /></p>
<p>To help illustrate conditional formatting, create another table of random integers between 1 and 100.   Excel&#8217;s <code>RAND()</code> function will generate a random number between 0 and 1, the formula we want is <code>=INT(RAND()*100)</code>.  The <code>ws.Range().Formula</code> construct can be used to fill a range with the same identical formula.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_rand.png" alt="20091019_rand" title="20091019_rand" width="545" height="37" class="alignnone size-full wp-image-175" /></p>
<p>The Excel spreadsheet should now contain both the multiplication and random number tables.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_twotables.png" alt="20091019_twotables" title="20091019_twotables" width="550" height="428" class="alignnone size-full wp-image-176" /></p>
<p>Now that the data is ready, conditional formatting can be applied.  Even though you invoked Excel from Python, you still can manipulate the spreadsheet using the Excel interface, and even record macros.  You need to record a macro like you did in the <a href="http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python">last post</a> in order to capture the VB commands, so click on Record Macro in the Developer tab, then click OK in the popup dialog. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_recordmacro.png" alt="20091019_recordmacro" title="20091019_recordmacro" width="587" height="260" class="alignnone size-full wp-image-177" /></p>
<p>Select all the cells in the range <code>B2:K22</code>.  In the Home tab, select Conditional Formatting->Color Scales->Red-Yellow-Blue Color Scale.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_condformat.png" alt="20091019_condformat" title="20091019_condformat" width="558" height="380" class="alignnone size-full wp-image-178" /></p>
<p>The spreadsheet should now show a color background for each of the selected cells containing a value.  Now select cell A1, then stop the macro by clicking Stop Recording in the Developer tab.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_stoprecording.png" alt="20091019_stoprecording" title="20091019_stoprecording" width="246" height="142" class="alignnone size-full wp-image-179" /></p>
<p>Your spreadsheet will now have conditional formatting applied and will look something like this, with cells containing numbers near 100 colored in Red, cells with a value of 50 in Yellow, and cells with a value of 1 in Blue, with a shade of these colors for values in between: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_formatted.png" alt="20091019_formatted" title="20091019_formatted" width="550" height="428" class="alignnone size-full wp-image-180" /></p>
<p>As an aside, you can update the random numbers in the lower table by hitting the F9 key to force a spreadsheet recalculation.</p>
<p>To continue, open the macro just created by selecting Macros from the Developer tab, select the name of the macro you just captured and click Edit.  The macro should look something like this: </p>
<pre class="brush: vb;">
Sub Macro1()
'
' Macro1 Macro
'
    Range(&quot;B2:K22&quot;).Select
    Selection.FormatConditions.AddColorScale ColorScaleType:=3
    Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
    Selection.FormatConditions(1).ColorScaleCriteria(1).Type = _
        xlConditionValueLowestValue
    With Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor
        .Color = 13011546
        .TintAndShade = 0
    End With
    Selection.FormatConditions(1).ColorScaleCriteria(2).Type = _
        xlConditionValuePercentile
    Selection.FormatConditions(1).ColorScaleCriteria(2).Value = 50
    With Selection.FormatConditions(1).ColorScaleCriteria(2).FormatColor
        .Color = 8711167
        .TintAndShade = 0
    End With
    Selection.FormatConditions(1).ColorScaleCriteria(3).Type = _
        xlConditionValueHighestValue
    With Selection.FormatConditions(1).ColorScaleCriteria(3).FormatColor
        .Color = 7039480
        .TintAndShade = 0
    End With
    Range(&quot;A1&quot;).Select
End Sub
</pre>
<p>Though the macro contains some very long method names, plus some <code>With</code> statements, the porting will be very straightforward.  Here are some guidelines to keep in mind while migrating this code to Python.</p>
<p><strong><code>Selection</code> is preceded by <code>excel.</code></strong></p>
<p>Remember that <code>Selection</code> is a method at the Excel Application level, you need to precede it with <code>excel.</code> in this example.  </p>
<p><strong><code>Range</code> is preceded by <code>ws.</code></strong><br />
<code>Range</code> is a method at the Worksheet level, which is defined earlier as <code>ws.</code> in this example.  </p>
<p><strong>Function calls require <code>()</code> in Python</strong><br />
Unlike VB, any function calls must by followed by <code>()</code> in Python.</p>
<p><strong><code>With</code> statements must be expanded</strong><br />
The three <code>With</code> blocks in this macro need to be expanded, which can be done with temporary variables or by copying the statement following the <code>With</code> keyword.  For example, the first <code>With</code> block:</p>
<pre class="brush: vb;">
With Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor
    .Color = 13011546
    .TintAndShade = 0
End With
</pre>
<p>can be written in Python as </p>
<pre class="brush: python;">
excel.Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor.Color = 13011546
excel.Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor.TintAndShade = 0
</pre>
<p>or by using a temporary variable as</p>
<pre class="brush: python;">
x = excel.Selection.FormatConditions(1).ColorScaleCriteria(1).FormatColor
x.Color = 13011546
x.FormatColor.TintAndShade = 0
</pre>
<p>Temporary variables were created to make the script more concise.  In particular, the statement <code>[csc1,csc2,csc3] = [excel.Selection.FormatConditions(1).ColorScaleCriteria(n) for n in range(1,4)]</code> was used to create three temporary variables for the three ColorScaleCriteria methods.  The equivalent Python text representing the macro is shown here: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_portedmacro.png" alt="20091019_portedmacro" title="20091019_portedmacro" width="550" height="255" class="alignnone size-full wp-image-181" /></p>
<p>To save the spreadsheet and close Excel, use the <code>SaveAs</code> and <code>Quit</code> methods as shown below. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091019_excelquit.png" alt="20091019_excelquit" title="20091019_excelquit" width="550" height="47" class="alignnone size-full wp-image-182" /></p>
<p>Here is the complete conditionalformatting.py script.  The line <code>excel.Visible = True</code> has been commented out.  Unless you are developing the script, you typically want Excel to run invisibly in the background. </p>
<pre class="brush: python;">
#
# conditionalformatting.py
# Create two tables and apply Conditional Formatting
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
#excel.Visible = True
wb = excel.Workbooks.Add()
ws = wb.Worksheets('Sheet1')
ws.Range(&quot;B2:K2&quot;).Value = [i for i in range(1,11)]
ws.Range(&quot;B2:B11&quot;).Value = zip([i for i in range(1,11)])
ws.Range(&quot;C3&quot;).Formula = &quot;=$B3*C$2&quot;
ws.Range(&quot;C3:C3&quot;).Select()
excel.Selection.AutoFill(ws.Range(&quot;C3:K3&quot;),win32.constants.xlFillDefault)
ws.Range(&quot;C3:K3&quot;).Select()
excel.Selection.AutoFill(ws.Range(&quot;C3:K11&quot;),win32.constants.xlFillDefault)
ws.Range(&quot;B13:K22&quot;).Formula = &quot;=INT(RAND()*100)&quot;
ws.Range(&quot;B2:K22&quot;).Select()
excel.Selection.FormatConditions.AddColorScale(ColorScaleType = 3)
excel.Selection.FormatConditions(excel.Selection.FormatConditions.Count).SetFirstPriority()
[csc1,csc2,csc3] = [excel.Selection.FormatConditions(1).ColorScaleCriteria(n) for n in range(1,4)]
csc1.Type = win32.constants.xlConditionValueLowestValue
csc1.FormatColor.Color = 13011546
csc1.FormatColor.TintAndShade = 0
csc2.Type = win32.constants.xlConditionValuePercentile
csc2.Value = 50
csc2.FormatColor.Color = 8711167
csc2.FormatColor.TintAndShade = 0
csc3.Type = win32.constants.xlConditionValueHighestValue
csc3.FormatColor.Color = 7039480
csc3.FormatColor.TintAndShade = 0
ws.Range(&quot;A1&quot;).Select()
wb.SaveAs('ConditionalFormatting.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program conditionalformatting.py script is available at<br /><a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>That&#8217;s all for now, thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python-revisited/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mapping Excel VB Macros to Python</title>
		<link>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python/</link>
		<comments>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 03:55:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=132</guid>
		<description><![CDATA[A handy feature in Excel is the ability to quickly record a Visual Basic (VB) macro and save it.   It&#8217;s also fairly simple to take a captured VB macro, tweak it slightly and use it in your Python scripts.  I&#8217;ve used this capability dozens of times over the years to capture a [...]]]></description>
			<content:encoded><![CDATA[<p>A handy feature in Excel is the ability to quickly record a Visual Basic (VB) macro and save it.   It&#8217;s also fairly simple to take a captured VB macro, tweak it slightly and use it in your Python scripts.  I&#8217;ve used this capability dozens of times over the years to capture a sequence of operations that modify a spreadsheet and build a pivot table or chart, then integrate the macro into a Python script.  It wasn&#8217;t always apparent to me how I could take the macro and use it within Python or other scripting languages beside Visual Basic, but I now have a pretty good grasp and want to share the technique with you.  </p>
<p>This exercise will illustrate how to capture a simple set of operations in a macro, examine the Visual Basic macro, port it to Python and run it.  I&#8217;m using the MultiplicationTable.xlsx file as a starting point, it&#8217;s a simple 10&#215;10 multiplication table that will be expanded and reformatted.  The first step is to capture the macro in Excel using Record Macro.  In Excel 2007 the Developer tab containing the Record Macro button is turned off by default, you will need to enable it by selecting &#8220;Excel Options&#8221; from the ribbon menu, then select &#8220;Popular&#8221; in the left hand column and select the &#8220;Show Developer tab in the Ribbon&#8221; checkbox as shown here.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_exceloptions.png" alt="20091012_exceloptions" title="20091012_exceloptions" width="600" height="488" class="alignnone size-full wp-image-133" /></p>
<p>Starting with a simple spreadsheet containing a table of data, click on the &#8220;Developer&#8221; tab, then &#8220;Record Macro&#8221;.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_recordmacro.png" alt="20091012_recordmacro" title="20091012_recordmacro" width="600" height="340" class="alignnone size-full wp-image-134" /></p>
<p>If you&#8217;re using an older version of Excel, select Tools->Macro->Record New Macro from the menu as shown here.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_recordmacroexcel2003.png" alt="20091012_recordmacroexcel2003" title="20091012_recordmacroexcel2003" width="435" height="366" class="alignnone size-full wp-image-165" /></p>
<p>The goal is to expand the existing table to a 15&#215;15 table, adjust the column width to make the table appear more square and save the new spreadsheet.  Now that the macro is recording, the first step is to select the last row of data and expanding it by dragging it down an additional 5 rows. First the data is selected</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_selectrow.png" alt="20091012_selectrow" title="20091012_selectrow" width="600" height="344" class="alignnone size-full wp-image-135" /></p>
<p>then dragged to create 5 new rows of data.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_dragrow.png" alt="20091012_dragrow" title="20091012_dragrow" width="600" height="429" class="alignnone size-full wp-image-136" /></p>
<p>Do the same select and drag operation for the last column of data to create 5 new columns. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_selectcolumn.png" alt="20091012_selectcolumn" title="20091012_selectcolumn" width="600" height="427" class="alignnone size-full wp-image-137" /></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_dragcolumn.png" alt="20091012_dragcolumn" title="20091012_dragcolumn" width="600" height="311" class="alignnone size-full wp-image-138" /></p>
<p>Now you have a 15&#215;15 multiplication table.  To resize the columns, select the headers for columns B through P, click the right mouse and select &#8220;Column Width&#8221;. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_columnwidth.png" alt="20091012_columnwidth" title="20091012_columnwidth" width="274" height="272" class="alignnone size-full wp-image-139" /></p>
<p>Enter &#8220;4&#8243; as the new column width and click OK. The spreadsheet will now look like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_resizecolumns.png" alt="20091012_resizecolumns" title="20091012_resizecolumns" width="596" height="522" class="alignnone size-full wp-image-140" /></p>
<p>Now stop capturing the macro by clicking on Stop Recording</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_stoprecording.png" alt="20091012_stoprecording" title="20091012_stoprecording" width="590" height="515" class="alignnone size-full wp-image-141" /></p>
<p>If you&#8217;re using an older version of Excel, select Tools->Macro->Stop Recording from the menu bar.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_stoprecordingexcel2003.png" alt="20091012_stoprecordingexcel2003" title="20091012_stoprecordingexcel2003" width="425" height="365" class="alignnone size-full wp-image-166" /></p>
<p>To view the macro, click on the View Macros button</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_viewmacros.png" alt="20091012_viewmacros" title="20091012_viewmacros" width="278" height="263" class="alignnone size-full wp-image-142" /></p>
<p>For older versions of Excel, select Tools->Macro->Macros</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_viewmacrosexcel2003.png" alt="20091012_viewmacrosexcel2003" title="20091012_viewmacrosexcel2003" width="437" height="368" class="alignnone size-full wp-image-167" /></p>
<p>Select the macro you just recorded (this should be Macro1, but if you were experimenting you may have other macros, so select the highest numbered macro) and click Edit. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_editmacro.png" alt="20091012_editmacro" title="20091012_editmacro" width="513" height="564" class="alignnone size-full wp-image-143" /><br />
This will open your macro in the Microsoft Visual Basic GUI, and it should look something like this</p>
<pre class="brush: vb;">
Sub Macro1()
'
' Macro1 Macro
'

'
    Range(&quot;B11:K11&quot;).Select
    Selection.AutoFill Destination:=Range(&quot;B11:K16&quot;), Type:=xlFillDefault
    Range(&quot;B11:K16&quot;).Select
    Range(&quot;K2:K16&quot;).Select
    Selection.AutoFill Destination:=Range(&quot;K2:P16&quot;), Type:=xlFillDefault
    Range(&quot;K2:P16&quot;).Select
    Columns(&quot;B:P&quot;).Select
    Selection.ColumnWidth = 4
End Sub
</pre>
<p>Don&#8217;t worry if there are some extra or redundant lines in your macro, they can be removed as the script is ported.  Now we&#8217;re ready to fire up Python and integrate this macro into a script. </p>
<p><strong>Porting</strong><br />
To get started, start the Python Integrated Development Enviroment (IDLE), then open the spreadsheet with the 10&#215;10 multiplication table by entering the following four commands (make sure the file &#8220;MultiplicationTable.xlsx&#8221; is in your My Documents folder.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_introidle.png" alt="20091012_introidle" title="20091012_introidle" width="677" height="487" class="alignnone size-full wp-image-144" /></p>
<p>Your screen should now look like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_introfullscreen.png" alt="20091012_introfullscreen" title="20091012_introfullscreen" width="600" height="725" class="alignnone size-full wp-image-145" /></p>
<p>These are boilerplate commands you&#8217;ll be using in each exercise.  The first two commands, <code>import win32com.client as win32</code>, and <code>excel = win32.gencache.EnsureDispatch( 'Excel.Application')</code>, import the win32 module and open the Excel process.  The command <code>wb = excel.Workbooks.Open('MultiplicationTable.xlsx')</code> opens the worksheet.  In general, you&#8217;ll need a <code>excel.Workbooks.Open()</code> or <code>excel.Workbooks.Add()</code> command to open an existing workbook or create a new workbook.  The command <code>excel.Visible = True</code> makes Excel visible on the screen, rather than running as a hidden process in the background.  </p>
<p>Looking at the Macro1 macro, the first command is <code>Range("B11:K11").Select</code>.  The <code>Range</code> variable name is within the context of the Worksheet, so you need to create a container for operations on the worksheet.  The command <code>ws = wb.Worksheets('Sheet1')</code> will do the trick. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_wsworksheet.png" alt="20091012_wsworksheet" title="20091012_wsworksheet" width="677" height="359" class="alignnone size-full wp-image-146" /></p>
<p>If you noticed, I made a typo when entering the command and typed <code>Worksheet</code> instead of <code>Worksheets</code>. Don&#8217;t panic if you make a mistake as I did, in most cases you can simply retype the correct command and continue on.</p>
<p>Once the variable pointing to the worksheet is defined, append the macro command to <code>ws.</code> and try it.   Note that <code>Select</code> is a function and requires the open and close parenthesis pair in order to operate correctly.  This pattern may be used for every <code>Range().Select</code> line in the macro. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_wsb11k11select.png" alt="20091012_wsb11k11select" title="20091012_wsb11k11select" width="677" height="73" class="alignnone size-full wp-image-147" /></p>
<p>If you bring the worksheet to the foreground, you&#8217;ll see that the range B11:K11 has been selected.  The next task is to autofill the 5 rows below using the <code>Selection.AutoFill Destination:=Range("B11:K16"), Type:=xlFillDefault</code> construct.  <code>Selection</code> is a method at the Excel Application level, you need to precede it with <code>excel.</code> in this example.  The arguments <code>Destination:=Range("B11:K16"), Type:=xlFillDefault</code> must be provided to the function, either using the keyword arguments <code>Destination</code> and <code>Type</code>, or by using positional notation.  To make your programs as robust as possible, you should include the keywords, but it&#8217;s not strictly required and I don&#8217;t use that pattern in this example. </p>
<p>The definition for the constant <code>xlFillDefault</code> is contained in  <code>win32.constants</code>, you can access this value by specifying <code>win32.constants.xlFillDefault</code>.  I&#8217;ve seen many examples where the developer replaces this with the actual value (0 in this case).  My preference is to avoid replacing Excel variables with numbers in my scripts, I believe that including the variable names increases the clarity of the script. My preference is to use the fully specified name wherever possible, but if you have to replace the variable with the actual value, you can always use the Object Browser in the VB window to figure out the correct value (open the Object Browser by pressing F2, or by selecting View->Object Browser from the menu in the VB window.  </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_vbobjectbrowser.png" alt="20091012_vbobjectbrowser" title="20091012_vbobjectbrowser" width="404" height="567" class="alignnone size-full wp-image-148" /></p>
<p>Combining these translations, the full Python command is <code>excel.Selection.AutoFill( Destination=ws.Range("B11:K16"), Type=win32.constants.xlFillDefault )</code>, or <code>excel.Selection.AutoFill( ws.Range("B11:K16"), win32.constants.xlFillDefault)</code> as I&#8217;ve used in the example. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_idlefillrow.png" alt="20091012_idlefillrow" title="20091012_idlefillrow" width="677" height="72" class="alignnone size-full wp-image-149" /></p>
<p>Occasionally you&#8217;ll make a mistake when capturing a macro and record extraneous, unnecessary commands.  The command <code>Range("B11:K16").Select</code> isn&#8217;t needed and can be ignored.  The next two macro commands, <code>Range("K2:K16").Select</code> and <code>Selection.AutoFill Destination:=Range("K2:P16"), Type:=xlFillDefault</code>,  are translated in the same way as the <code>Select</code> and <code>AutoFill</code> commands discussed earlier. </p>
<p>The commands <code>Range("K2:K16").Select</code> and <code>Selection.AutoFill Destination:=Range("K2:P16"), Type:=xlFillDefault</code> are translated in the same fashion as the earlier <code>Select</code> and <code>AutoFill</code> commands as shown below.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_idlefillcolumn.png" alt="20091012_idlefillcolumn" title="20091012_idlefillcolumn" width="677" height="104" class="alignnone size-full wp-image-150" /></p>
<p>The worksheet is now expanded to the full 15&#215;15 table and looks like this:</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_worksheetfilled.png" alt="20091012_worksheetfilled" title="20091012_worksheetfilled" width="600" height="296" class="alignnone size-full wp-image-151" /></p>
<p>The next section of the macro selects columns B through P and sets their width to 4.  The statement <code>Columns("B:P").Select</code> is a property of the worksheet, so prefix it with the <code>ws.</code> identifier and add the parenthesis to make it a Python function call.  In the next statement, <code>Selection</code> is a property of <code>excel</code>, so prefix it as such.  The translated statements are shown below.</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_idlecolumnwidth.png" alt="20091012_idlecolumnwidth" title="20091012_idlecolumnwidth" width="677" height="88" class="alignnone size-full wp-image-152" /></p>
<p>The Excel spreadsheet is now complete, the multiplication table has been expanded to 15&#215;15 and the columns have been resized to 4.  At this point, translation of the macro is complete, but the modified file has to be saved.  To write the file and quit Excel, use the <code>SaveAs</code> and <code>Quit</code> methods as shown below. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/10/20091012_idlesavequit.png" alt="20091012_idlesavequit" title="20091012_idlesavequit" width="677" height="71" class="alignnone size-full wp-image-153" /></p>
<p>For your reference, here is the completed Python script.</p>
<pre class="brush: python;">
#
# make15x15.py
# Expand an existing 10x10 multiplication table and resize columns
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open('MultiplicationTable.xlsx')
excel.Visible = True
ws = wb.Worksheets('Sheet1')
ws.Range(&quot;B11:K11&quot;).Select()
excel.Selection.AutoFill(ws.Range(&quot;B11:K16&quot;),win32.constants.xlFillDefault)
ws.Range(&quot;K2:K16&quot;).Select()
excel.Selection.AutoFill(ws.Range(&quot;K2:P16&quot;),win32.constants.xlFillDefault)
ws.Columns(&quot;B:P&quot;).Select()
excel.Selection.ColumnWidth = 4
wb.SaveAs('NewMultiplicationTable.xlsx')
excel.Application.Quit()
</pre>
<p>If this is the first time you&#8217;ve ported an Excel macro from VB to Python, congratulations!  Please note that in this example, things are kept simple and there is absolutely no error checking illustrated.  Normally you would need to provide at least a minimal level of error checking in your script so that common errors (missing input file, can&#8217;t invoke Excel, etc) are caught and handled nicely.  Also, this example was developed using Excel 2007, but you can run this code verbatim on earlier versions of Excel if you change the <code>.xlsx</code> file extension to <code>.xls</code> throughout the script.
</ul>
<p><strong>Some Porting Guidelines</strong> </p>
<ol>
<li>Prefix the <code>Range().Select</code> statements with the variable name pointing to the  worksheet (<code>ws</code> in this example)</li>
<li>Append <code>()</code> to any functions</li>
<li>Prefix the <code>Selection</code> statements with the variable name for the Excel spreadsheet (<code>excel</code> in this example)</li>
<li>Prefix the <code>Columns</code> statements with the variable name for the worksheet(<code>ws</code> in this example)</li>
</ol>
<p><strong>Porting Reference Table for this example</strong><br />
Note that I didn&#8217;t capture the <code>Workbooks.Open()</code> or <code>Workbooks.SaveAs</code> lines in the VB script, it&#8217;s left as an exercise for the reader to research those commands. </p>
<table border=1>
<tr>
<th>VB</th>
<th>Python</th>
</tr>
<tr>
<td>&#8211;</td>
<td>
import win32com.client as win32<br />
excel = win32.gencache.EnsureDispatch(&#8217;Excel.Application&#8217;)<br />
wb = excel.Workbooks.Open(&#8217;MultiplicationTable.xlsx&#8217;)<br />
excel.Visible = True<br />
ws = wb.Worksheets(&#8217;Sheet1&#8242;)</td>
</tr>
<tr>
<td>Range(&#8221;B11:K11&#8243;).Select</td>
<td>ws.Range(&#8221;B11:K11&#8243;).Select()</td>
</tr>
<tr>
<td>Range(&#8221;B11:K11&#8243;).Select</td>
<td>ws.Range(&#8221;B11:K11&#8243;).Select()</td>
</tr>
<tr>
<td>Selection.AutoFill Destination:=Range(&#8221;B11:K16&#8243;), Type:=xlFillDefault</td>
<td>excel.Selection.AutoFill(ws.Range(&#8221;B11:K16&#8243;),win32.constants.xlFillDefault)</td>
</tr>
<tr>
<td>Range(&#8221;K2:K16&#8243;).Select</td>
<td>ws.Range(&#8221;K2:K16&#8243;).Select()</td>
</tr>
<tr>
<td>Selection.AutoFill Destination:=Range(&#8221;K2:P16&#8243;), Type:=xlFillDefault</td>
<td>excel.Selection.AutoFill(ws.Range(&#8221;K2:P16&#8243;),win32.constants.xlFillDefault)</td>
</tr>
<tr>
<td>Range(&#8221;K2:P16&#8243;).Select</td>
<td>ws.Columns(&#8221;B:P&#8221;).Select()</td>
</tr>
<tr>
<td>Columns(&#8221;B:P&#8221;).Select</td>
<td>ws.Columns(&#8221;B:P&#8221;).Select()</td>
</tr>
<tr>
<td>Selection.ColumnWidth = 4</td>
<td>excel.Selection.ColumnWidth = 4</td>
</tr>
<tr>
<td>&#8211;</td>
<td>wb.SaveAs(&#8217;NewMultiplicationTable.xlsx&#8217;)<br />
excel.Application.Quit()</td>
</tr>
</table>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program make15&#215;15.py and data text file are available at<br /><a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>That&#8217;s all for now, thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/10/mapping-excel-vb-macros-to-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python Excel Mini Cookbook</title>
		<link>http://www.pythonexcels.com/2009/10/python-excel-mini-cookbook/</link>
		<comments>http://www.pythonexcels.com/2009/10/python-excel-mini-cookbook/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 00:32:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=121</guid>
		<description><![CDATA[To get you started, I&#8217;ve illustrated a number of common tasks you can do with Python and Excel.   Each program below is a self contained example, just copy it, paste it and run it.  A few things to note: 

These examples were tested in Excel 2007, they should work fine in earlier [...]]]></description>
			<content:encoded><![CDATA[<p>To get you started, I&#8217;ve illustrated a number of common tasks you can do with Python and Excel.   Each program below is a self contained example, just copy it, paste it and run it.  A few things to note: </p>
<ol>
<li>These examples were tested in Excel 2007, they should work fine in earlier versions as well after changing the extension of the file within the  <code>wb.SaveAs()</code> statement from .xlsx to .xls</li>
<li>If you&#8217;re new to this, I recommend typing these examples by hand into IDLE, IPython or the Python interpreter, then watching the effect in Excel as you enter the commands.  To make Excel visible add the line
<p>&nbsp;</p>
<p><code>excel.Visible = True</code></p>
<p>&nbsp;</p>
<p>after the <code>excel = win32.gencache.EnsureDispatch('Excel.Application')</code> line in the script</li>
<li>These are simple examples with no error checking.  Make sure the output files doesn&#8217;t exist before running the script.  If the script crashes, it may leave a copy of Excel running in the background.  Open the Windows Task Manager and kill the background Excel process to recover.  </li>
<li>These examples contain no optimization.  You typically wouldn&#8217;t use a <code>for</code> loop to iterate through data in individual cells, it&#8217;s provided here for illustration only.</li>
</ol>
<p><strong>Open Excel, Add a Workbook</strong><br />
The following script simply invokes Excel, adds a workbook and saves the empty workbook.</p>
<pre class="brush: python;">
#
# add_a_workbook.py
# Add a workbook and save (Excel 2007)
# For older versions of excel, use the .xls file extension
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
wb.SaveAs('add_a_workbook.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Open an Existing Workbook</strong><br />
This script opens an existing workbook and displays it (note the statement <code>excel.Visible = True</code>).  The file workbook1.xlsx would exist in the user&#8217;s &#8220;My Documents&#8221; directory.  You can also open spreadsheet files by specifying the full path to the file as shown below.  Using <code>r'</code> in the statement <code>r'C:\myfiles\excel\workbook2.xlsx'</code> automatically escapes the backslash characters and makes the file name a bit more concise. </p>
<pre class="brush: python;">
#
# open_an_existing_workbook.py
# Open an existing workbook
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open('workbook1.xlsx')
# Alternately, specify the full path to the workbook
# wb = excel.Workbooks.Open(r'C:\myfiles\excel\workbook2.xlsx')
excel.Visible = True
</pre>
<p><strong>Add a Worksheet</strong><br />
This script creates a new workbook with three sheets, adds a fourth worksheet and names it MyNewSheet. </p>
<pre class="brush: python;">
#
# add_a_worksheet.py
# Add a workbook, add a worksheet,
# name it 'MyNewSheet' and save
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets.Add()
ws.Name = &quot;MyNewSheet&quot;
wb.SaveAs('add_a_worksheet.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Ranges and Offsets</strong><br />
This script uses some different techniques for addressing cells using the <code>Cells()</code> and <code>Range()</code> operators. Individual cells can be addressed using <code>Cells(row,column)</code>, where <code>row</code> is the row number, <code>column</code> is the column number, both start from 1. Groups of cells can be addressed using <code>Range()</code>, where the argument in the parenthesis can be a single cell denoted by its textual name (eg <code>"A2"</code>), a group noted by a textual name with a colon (eg <code>"A3:B4"</code>) or a group denoted with two <code>Cells()</code> identifiers (eg <code>ws.Cells(1,1),ws.Cells(2,2)</code>). The <code>Offset</code> method provides a way to address a cell based on a reference to another cell. </p>
<pre class="brush: python;">
#
# ranges_and_offsets.py
# Using ranges and offsets
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
ws.Cells(1,1).Value = &quot;Cell A1&quot;
ws.Cells(1,1).Offset(2,4).Value = &quot;Cell D2&quot;
ws.Range(&quot;A2&quot;).Value = &quot;Cell A2&quot;
ws.Range(&quot;A3:B4&quot;).Value = &quot;A3:B4&quot;
ws.Range(&quot;A6:B7,A9:B10&quot;).Value = &quot;A6:B7,A9:B10&quot;
wb.SaveAs('ranges_and_offsets.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Autofill Cell Contents</strong><br />
This script uses Excel&#8217;s autofill capability to examine data in cells A1 and A2, then autofill the remaining column of cells through A10.</p>
<pre class="brush: python;">
#
# autofill_cells.py
# Autofill cell contents
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
ws.Range(&quot;A1&quot;).Value = 1
ws.Range(&quot;A2&quot;).Value = 2
ws.Range(&quot;A1:A2&quot;).AutoFill(ws.Range(&quot;A1:A10&quot;),win32.constants.xlFillDefault)
wb.SaveAs('autofill_cells.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Cell Color</strong><br />
This script illustrates adding an interior color to the cell using <code>Interior.ColorIndex</code>.  Column A, rows 1 through 20 are filled with a number and assigned that <code>ColorIndex</code>. </p>
<pre class="brush: python;">
#
# cell_color.py
# Add an interior color to cells
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
for i in range (1,21):
    ws.Cells(i,1).Value = i
    ws.Cells(i,1).Interior.ColorIndex = i
wb.SaveAs('cell_color.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Column Formatting</strong><br />
This script creates two columns of data, one narrow and one wide, then formats the column width with the <code>ColumnWidth</code> property.  You can also use the <code>Columns.AutoFit()</code> function to autofit all columns in the spreadsheet. </p>
<pre class="brush: python;">
#
# column_widths.py
# Set column widths
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
ws.Range(&quot;A1:A10&quot;).Value = &quot;A&quot;
ws.Range(&quot;B1:B10&quot;).Value = &quot;This is a very long line of text&quot;
ws.Columns(1).ColumnWidth = 1
ws.Range(&quot;B:B&quot;).ColumnWidth = 27
# Alternately, you can autofit all columns in the worksheet
# ws.Columns.AutoFit()
wb.SaveAs('column_widths.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Copying Data from Worksheet to Worksheet</strong><br />
This script uses the <code>FillAcrossSheets()</code> method to copy data from one location to all other worksheets in the workbook.  Specifically, the data in the range A1:J10 is copied from Sheet1 to sheets Sheet2 and Sheet3.  </p>
<pre class="brush: python;">
#
# copy_worksheet_to_worksheet.py
# Copy data and formatting from a range of one worksheet
# to all other worksheets in a workbook
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
ws.Range(&quot;A1:J10&quot;).Formula = &quot;=row()*column()&quot;
wb.Worksheets.FillAcrossSheets(wb.Worksheets(&quot;Sheet1&quot;).Range(&quot;A1:J10&quot;))
wb.SaveAs('copy_worksheet_to_worksheet.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Format Worksheet Cells</strong><br />
This example creates two columns of data, then formats the font type and font size used in the worksheet.  Five different fonts and sizes are used, the numbers are formatted using a monetary format. </p>
<pre class="brush: python;">
#
# format_cells.py
# Format cell font name and size, format numbers in monetary format
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)

for i,font in enumerate([&quot;Arial&quot;,&quot;Courier New&quot;,&quot;Garamond&quot;,&quot;Georgia&quot;,&quot;Verdana&quot;]):
    ws.Range(ws.Cells(i+1,1),ws.Cells(i+1,2)).Value = [font,i+i]
    ws.Range(ws.Cells(i+1,1),ws.Cells(i+1,2)).Font.Name = font
    ws.Range(ws.Cells(i+1,1),ws.Cells(i+1,2)).Font.Size = 12+i

ws.Range(&quot;A1:A5&quot;).HorizontalAlignment = win32.constants.xlRight
ws.Range(&quot;B1:B5&quot;).NumberFormat = &quot;$###,##0.00&quot;
ws.Columns.AutoFit()
wb.SaveAs('format_cells.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Setting Row Height</strong><br />
Similar to column height, row height can be set with the <code>RowHeight</code> method.  You can also use <code>AutoFit()</code> to automatically adjust the row height based on cell contents.  </p>
<pre class="brush: python;">
#
# row_height.py
# Set row heights and align text within the cell
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets(&quot;Sheet1&quot;)
ws.Range(&quot;A1:A2&quot;).Value = &quot;1 line&quot;
ws.Range(&quot;B1:B2&quot;).Value = &quot;Two\nlines&quot;
ws.Range(&quot;C1:C2&quot;).Value = &quot;Three\nlines\nhere&quot;
ws.Range(&quot;D1:D2&quot;).Value = &quot;This\nis\nfour\nlines&quot;
ws.Rows(1).RowHeight = 60
ws.Range(&quot;2:2&quot;).RowHeight = 120
ws.Rows(1).VerticalAlignment = win32.constants.xlCenter
ws.Range(&quot;2:2&quot;).VerticalAlignment = win32.constants.xlCenter

# Alternately, you can autofit all rows in the worksheet
# ws.Rows.AutoFit()

wb.SaveAs('row_height.xlsx')
excel.Application.Quit()
</pre>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel (refer to <a href="http://office.microsoft.com/excel">http://office.microsoft.com/excel</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program and data text file are available at<br /><a href="http://github.com/pythonexcels/examples">http://github.com/pythonexcels/examples</a></p>
<p>That&#8217;s all for now, thanks &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/10/python-excel-mini-cookbook/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Basic Excel Driving with Python</title>
		<link>http://www.pythonexcels.com/2009/09/basic-excel-driving-with-python/</link>
		<comments>http://www.pythonexcels.com/2009/09/basic-excel-driving-with-python/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 01:08:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=96</guid>
		<description><![CDATA[Now it&#8217;s getting interesting.  Reading and writing spreadsheets with XLRD and XLWT is sufficient for many tasks, and you don&#8217;t even need a copy of Excel to do it.  But to really open up your data and fully wring all the information possible from it, you&#8217;ll need Excel and its powerful set of [...]]]></description>
			<content:encoded><![CDATA[<p>Now it&#8217;s getting interesting.  Reading and writing spreadsheets with XLRD and XLWT is sufficient for many tasks, and you don&#8217;t even need a copy of Excel to do it.  But to really open up your data and fully wring all the information possible from it, you&#8217;ll need Excel and its powerful set of functions, pivot tables and charting.</p>
<p>For starters, let&#8217;s do some simple operations using Python to invoke Excel, add a spreadsheet, insert some data, then save the results to a spreadsheet file.  You can play along at home by following my lead and entering the program text exactly as I&#8217;ve described below.  My exercises and screen shots are done with Excel 2007, but all the commands presented here also work fine for Excel 2003.   A prerequisite for this exercise is Python, the <a href="http://sourceforge.net/projects/pywin32/">Win32</a> module and a copy of Microsoft Excel.</p>
<p>Here is the complete script we&#8217;ll be entering using IDLE, the Python interactive development tool. </p>
<pre class="brush: python;">
#
# driving.py
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True
wb = excel.Workbooks.Add()
ws = wb.Worksheets('Sheet1')
ws.Name = 'Built with Python'
ws.Cells(1,1).Value = 'Hello Excel'
print ws.Cells(1,1).Value
for i in range(1,5):
    ws.Cells(2,i).Value = i  # Slow!
ws.Range(ws.Cells(3,1),ws.Cells(3,4)).Value = [5,6,7,8]
ws.Range(&quot;A4:D4&quot;).Value = [i for i in range(9,13)]
ws.Cells(5,4).Formula = '=SUM(A2:D4)'
ws.Cells(5,4).Font.Size = 16
ws.Cells(5,4).Font.Bold = True
</pre>
<p>What follows is a step-by-step guide to entering this script and monitoring the result.</p>
<p><strong>1) Open the Python IDLE interface from the Start menu </strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlestartmenu.png" alt="Starting IDLE" title="Starting IDLE" width="521" height="300" class="alignnone size-full wp-image-97" /></p>
<p>&#8220;IDLE is the Python IDE built with the tkinter GUI toolkit&#8221;, as described in the <a href="http://docs.python.org/library/idle.html">Python IDLE documentation</a>, and gives you an interactive interface to enter, run and save Python programs.  IDLE isn&#8217;t strictly necessary for this exercise, you could use any shell command window, or a tool such as <a href="http://ipython.scipy.org/moin/">IPython</a> or the MS Windows command line interface.  </p>
<p><strong>2) Import the win32 module</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idleimport.png" alt="Import Win32 command" title="Import Win32 command" width="550" height="50" class="alignnone size-full wp-image-99" /></p>
<p>If the import command was successful, you&#8217;ll see the &#8220;>>>&#8221; prompt returned.  If there was a problem, such as not having the win32 module installed correctly, you&#8217;ll see <code>Import Error: No module named win32com.client</code>.  In that case, install the appropriate win32 module from the <a href="http://sourceforge.net/projects/pywin32/">web site</a>. </p>
<p><strong>3) Start Excel </strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idleexcel.png" alt="Invoke Excel" title="Invoke Excel" width="550" height="20" class="alignnone size-full wp-image-101" /></p>
<p>The command <code>win32.gencache.EnsureDispatch('Excel.Application')</code> will attach to an Excel process that is already running, or will start Excel if it&#8217;s not.  If you see the &#8220;>>>&#8221; prompt, Excel has been started or linked successfully. At this point you won&#8217;t see Excel, but if you check your task manager you can confirm that the process is running.</p>
<p><strong>4) Make Excel Visible</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlevisible.png" alt="Make Excel Visible" title="Make Excel Visible" width="550" height="20" class="alignnone size-full wp-image-102" /></p>
<p>Setting the Visible flag with <code>excel.Visible = True</code> makes the Excel window appear.  At this point, Excel does not contain any workbooks or worksheets, we&#8217;ll add those in the next step. </p>
<p><strong>5) Add a workbook, select the sheet &#8220;Sheet1&#8243; and rename it</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlewbws.png" alt="Add a workbook" title="Add a workbook" width="550" height="50" class="alignnone size-full wp-image-103" /></p>
<p>Excel needs a workbook to serve as a container for the worksheets.  A new workbook containing 3 sheets is added with command <code>wb = excel.Workbooks.Add()</code>.  The command <code>ws = wb.Worksheets('Sheet1')</code> assigns <code>ws</code> to the sheet named Sheet1, and the command <code>ws.Name = 'Built with Python'</code> changes the name of Sheet1.  Your screen should now look something like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelblank.png" alt="Empty Excel Spreadsheet" title="Empty Excel Spreadsheet" width="600" height="464" class="alignnone size-full wp-image-104" /></p>
<p><strong>6) Add some text into the first cell</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlehello.png" alt="Hello Excel" title="Hello Excel" width="550" height="50" class="alignnone size-full wp-image-105" /></p>
<p>Now the setup is complete and you can add data to the spreadsheet.  There are several options for addressing cells and blocks of data in Excel, we&#8217;ll cover a few of them here.  You can address individual cells with the <code>Cells(row,column).Value</code> pattern, where row and column are integer values representing the row and column location for the cell.  Use <code>.Value</code> to add text, numbers and date information to the cell, use <code>.Formula</code> for entering an Excel formula into the cell location.  </p>
<p>After these commands, you&#8217;ll see the &#8220;Hello Excel&#8221; text in your Excel worksheet, and see the text printed in the IDLE window as well.  Of course, Python can set values in the spreadsheet as well as query data from the speadsheet. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelhello.png" alt="Excel Hello" title="Excel Hello" width="329" height="237" class="alignnone size-full wp-image-106" /></p>
<p><strong>7) Populate the second row with data</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlefor.png" alt="For loop insertion" title="For loop insertion" width="550" height="50" class="alignnone size-full wp-image-107" /></p>
<p>In many cases you&#8217;ll have lists of data to insert into or extract from the worksheet.  Wrapping the <code>Cells(row,column).Value</code> pattern with a loop seems like a natural approach, but in reality this maximizes the communication overhead between Python and Excel and results in very inefficient and slow code.  It&#8217;s much better to transfer lists than individual elements whenever possible as shown in the next section.  After this command, your Excel spreadsheet will look like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelfor.png" alt="For loop results in Excel" title="For loop results in Excel" width="329" height="237" class="alignnone size-full wp-image-109" /></p>
<p><strong>8) Populate the third and fourth rows of data</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idlerange.png" alt="Range insertion" title="Range insertion" width="550" height="30" class="alignnone size-full wp-image-110" /></p>
<p>A better approach to populating or extracting blocks of data is to use the <code>Range().Value</code> pattern.  With this construct you can efficiently transfer a one- or two-dimensional blocks of data.  In the first example, cells (3,1) through (3,4) are assigned to the list [5,6,7,8].  The next line uses the Excel-style cell address &#8220;A4:D4&#8243; to assign the results of the operation <code>[i for i in range(9,13)]</code>.  In some cases, it may be more intuitive to use the Excel-style naming.  The Excel sheet now looks like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelfourrows.png" alt="Excel data insertion" title="Excel data insertion" width="329" height="237" class="alignnone size-full wp-image-111" /></p>
<p><strong>9) Assign a formula to sum the numbers just added</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idleformula.png" alt="Formula insertion" title="Formula insertion" width="550" height="20" class="alignnone size-full wp-image-112" /></p>
<p>You can insert Excel formulas into cells using the <code>.Formula</code> pattern.  The formula is the same as if you were to enter it in Excel: <code>=SUM(A2:D4)</code>.  In this example, the sum of 12 numbers in rows 2,3 and 4 is generated.  Your Excel sheet should now look like the screenshot below. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelformula.png" alt="Excel Formula" title="Excel Formula" width="329" height="237" class="alignnone size-full wp-image-113" /></p>
<p><strong>10) Change the formatting of the formula cell</strong></p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_idleformat.png" alt="Formatting data" title="Formatting data" width="550" height="30" class="alignnone size-full wp-image-114" /></p>
<p>As a final exercise, the format of the formula cell is changed to point size 16 with a bold typeface.  You can change any of dozens of attributes for the various cells in the worksheet through Python.  Your spreadsheet should now look like this. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090929_excelformat.png" alt="Formatting result in Excel" title="Formatting result in Excel" width="329" height="237" class="alignnone size-full wp-image-115" /></p>
<p>Hopefully you did this exercise interactively, typing the commands and monitoring the result in Excel.  You can also cut to the chase and run this script to generate the result.  When the script exits, you&#8217;ll be left with an open Excel spreadsheet just as shown in the last screenshot above.  </p>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>Win32 Python module (refer to <a href="http://sourceforge.net/projects/pywin32">http://sourceforge.net/projects/pywin32</a>)</p>
<p>Microsoft Excel</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program and data text file are available at<br /><a href="http://github.com/pythonexcels/examples/tree/master">http://github.com/pythonexcels/examples/tree/master</a></p>
<p><strong>References</strong></p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.amazon.com/Core-Python-Programming-Wesley-Chun/dp/0132269937">Core Python Programming</a></td>
<td>Wesley Chun&#8217;s book has a chapter on Programming Microsoft Office with Win32 COM</td>
</tr>
<tr>
<td><a href="http://groups.google.com/group/python-excel">http://groups.google.com/group/python-excel</a></td>
<td>Though this group mainly covers questions on the excellent XLRD, XLWT and XLUTILS modules, there is also some discussion on interfacing to Excel using Win32 COM</td>
</tr>
<tr>
<td><a href="http://stackoverflow.com/search?q=python+excel">Stack Overflow</a></td>
<td>Stack Overflow is a great resource for getting questions answered on a variety of programming topics, including Python</td>
</tr>
</tbody>
</table>
<p>Thanks everyone &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/09/basic-excel-driving-with-python/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Another XLWT Example</title>
		<link>http://www.pythonexcels.com/2009/09/another-xlwt-example/</link>
		<comments>http://www.pythonexcels.com/2009/09/another-xlwt-example/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 02:44:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=67</guid>
		<description><![CDATA[After completing the last example, I wanted to try something a little more interesting with XLWT this time around.  This article describes a short script that uses Python and XLWT to download some raw data from the web, parse it, and write a spreadsheet with a new column derived from the data.   [...]]]></description>
			<content:encoded><![CDATA[<p>After completing the <a href="http://www.pythonexcels.com/2009/09/using-xlwt-to-write-spreadsheets-without-excel/">last example</a>, I wanted to try something a little more interesting with XLWT this time around.  This article describes a short script that uses Python and XLWT to download some raw data from the web, parse it, and write a spreadsheet with a new column derived from the data.   The data for this example comes from research done by David Harrison and Daniel L. Rubinfeld in &#8220;Hedonic Housing Prices and the Demand for Clean Air&#8221;, published in the Journal of Environmental Economics and Management, Volume 5, (1978), and contains information on location, pricing, tax and other information from the Boston housing market.  I&#8217;ll be illustrating three things in this script: </p>
<ul>
<li>Downloading data directly from the web
<li>Parsing the data, removing extraneous information at the top of the file and writing the real data fields to a spreadsheet
<li>Adding a hyperlink for each record that links to a Google Map, based on the latitude and longitude data given
</ul>
<p>Note that it&#8217;s possible to do these steps using a web browser and an interactive Excel session.  You can easily download the file, import it into Excel, remove the leading text, and make a formula to produce a hyperlink.  But the beauty of this script is that everything is done automatically, which can be very handy if the source data is constantly updated.  </p>
<p>Here&#8217;s the script that performs these operations: </p>
<pre class="brush: python;">
#
# xlwt_bostonhousing.py
#
import sys
from urllib2 import urlopen
from xlwt import Workbook, easyxf, Formula

def doxl():
    '''Read the boston_corrected.txt file based on
       Harrison, David, and Daniel L. Rubinfeld, &quot;Hedonic Housing Prices
       and the Demand for Clean Air,&quot; Journal of Environmental Economics
       and Management, Volume 5, (1978), write to an excel spreadsheet .
       '''
    URL = 'http://stat.cmu.edu/datasets/boston_corrected.txt'
    try:
        fp = urlopen(URL)
    except:
        print 'Failed to download %s' % URL
        sys.exit(1)
    lines = fp.readlines()

    wb = Workbook()
    ws = wb.add_sheet('Housing Data')
    ulstyle = easyxf('font: underline single')
    r = 0
    for line in lines:
        tokens = line.strip().split('\t')
        if len(tokens) != 21:
            continue
        for c,t in enumerate(tokens):
            for dtype in (int,float):
                try:
                    t = dtype(t)
                except:
                    pass
                else:
                    break
            ws.write(r,c+1,t)
        if r == 0:
            hdr = tokens
            ws.write(r,0,'MAPLINK')
        else:
            d = dict(zip(hdr,tokens))
            link = 'HYPERLINK(&quot;http://maps.google.com/maps?q=%s,+%s+(Observation+%s)&amp;hl=en&amp;ie=UTF8&amp;z=14&amp;iwloc=A&quot;;&quot;MAP&quot;)' % (d['LAT'],d['LON'],d['OBS.'])
            ws.write(r,0,Formula(link),ulstyle)

        r += 1
    wb.save('bostonhousing.xls')
    print 'Wrote bostonhousing.xls'

if __name__ == &quot;__main__&quot;:
    doxl()
</pre>
<p>As in the previous post, you must have xlwt installed (please refer to the site <a href="http://www.python-excel.org">http://www.python-excel.org</a> for information on downloading and installing). Looking at the important bits in the script above, the lines </p>
<pre class="brush: python; first-line: 14">
    URL = 'http://stat.cmu.edu/datasets/boston_corrected.txt'
    try:
        fp = urlopen(URL)
    except:
        print 'Failed to download %s' % URL
        sys.exit(1)
    lines = fp.readlines()
</pre>
<p>open the URL for the boston_corrected.txt file, then reads the URL and returns a list of strings.  The next section: </p>
<pre class="brush: python; first-line: 22">
    wb = Workbook()
    ws = wb.add_sheet('Housing Data')
    ulstyle = easyxf('font: underline single')
    r = 0
</pre>
<p>creates a new Workbook object, then adds a sheet named &#8220;Housing Data&#8221; to the workbook.  The easyfx function provides a convenient way to add formatting to the spreadsheet; in this example, the single underline format is used to denote a hyperlink.  In the next line, the variable r acts as a row counter. </p>
<p>The <i>for</i> loop below examines each row of data: </p>
<pre class="brush: python; first-line: 26">
    for line in lines:
        tokens = line.strip().split('\t')
        if len(tokens) != 21:
            continue
        for c,t in enumerate(tokens):
            for dtype in (int,float):
                try:
                    t = dtype(t)
                except:
                    pass
                else:
                    break
            ws.write(r,c+1,t)
</pre>
<p>Each line is &#8220;stripped&#8221; (leading and trailing white space characters are removed), then split by tab characters.   A data line contains 21 fields of information, otherwise it is rejected.  To properly format the data for the spreadsheet, the datatype is set using  try-except-else within the <i>for</i> loop.  The loop only considers string, integer and float data, which is sufficient for this input data.  More complex input files may contain date information which would require additional handling.  The cell data with the correct type setting is written to the spreadsheet using the ws.write statement. </p>
<p>The next section builds the hyperlink to a Google Map using the latitude and longitude information within the input data.  </p>
<pre class="brush: python; first-line: 39">
        if r == 0:
            hdr = tokens
            ws.write(r,0,'MAPLINK')
        else:
            d = dict(zip(hdr,tokens))
            link = 'HYPERLINK("http://maps.google.com/maps?q=%s,+%s+(Observation+%s)&#038;hl=en&#038;ie=UTF8&#038;z=14&#038;iwloc=A";"MAP")' % (d['LAT'],d['LON'],d['OBS.'])
            ws.write(r,0,Formula(link),ulstyle)
        r += 1
    wb.save('bostonhousing.xls')
    print 'Wrote bostonhousing.xls'
</pre>
<p>If this is the first row of data (<i>if r == 0</i>), it is assumed to be header data and is saved in the hdr variable.  Otherwise, the statement <i>d = dict(zip(hdr,tokens))</i> builds a dictionary, using the header information as keys.  This allows each field to be referenced by its column heading.  The hyperlink is built by specifying a URL containing <i>http://maps.google.com/maps?</i>, with the corresponding latitude (<i>d['LAT']</i>) and longitude (<i>d['LON']</i>) information from the current line of data.  Finally, the hyperlink data is written to the spreadsheet with <i>ws.write</i>.  The last two lines write the spreadsheet and print a message. </p>
<p>The original raw data looks like this: </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090918_11.png" alt="Raw Data" title="Raw Data" width="632" height="419" class="alignnone size-full wp-image-81" /></p>
<p>The bostonhousing.xls spreadsheet containing the original data and the new map hyperlink looks like this:</p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090918_2.png" alt="Bostonhousing.xls" title="Bostonhousing.xls" width="646" height="399" class="alignnone size-full wp-image-82" /><br />
<br />
Clicking on the MAP link brings up a Google Map showing the location according to the latitude and longitude.  For some reason, the location of latitude 42.255000 and longitude -70.955000 isn&#8217;t in the town of Nahant, but in the middle of Rock Island Cove near Quincy.  It&#8217;s left as an exercise for the reader to determine why this is so. </p>
<p><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090918_3.png" alt="Google Map for latitude 42.255 and longitude -70.955" title="Google Map for latitude 42.255 and longitude -70.955" width="587" height="580" class="alignnone size-full wp-image-90" /></p>
<hr />
<strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>xlwt (refer to <a href="http://www.python-excel.org">http://www.python-excel.org</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program and data text file are available at<br /><a href="http://github.com/pythonexcels/xlwt/tree/master">http://github.com/pythonexcels/xlwt/tree/master</a></p>
<p><strong>References</strong></p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.python-excel.org">http://www.python-excel.org</a></td>
<td>This site contains pointers to the best information available about working with Excel files in the Python programming language.</td>
</tr>
<tr>
<td><a href="http://groups.google.com/group/python-excel">http://groups.google.com/group/python-excel</a></td>
<td>Google group for questions on xlrd, xlwt, xlutils and general questions on interfacing to Excel with Python</td>
</tr>
</tbody>
</table>
<p>Thanks everyone &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/09/another-xlwt-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using XLWT to Write Spreadsheets Without Excel</title>
		<link>http://www.pythonexcels.com/2009/09/using-xlwt-to-write-spreadsheets-without-excel/</link>
		<comments>http://www.pythonexcels.com/2009/09/using-xlwt-to-write-spreadsheets-without-excel/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 19:15:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=26</guid>
		<description><![CDATA[Long before I even started thinking about writing a blog covering the integration possibilities between Excel and Python, the boys at Simplistix (http://www.simplistix.co.uk) were crafting some of the handiest Python modules around: xlrd, xlwt and xlutils.  These fantastic modules enable Python to directly read and write an Excel .xls file, without the need for [...]]]></description>
			<content:encoded><![CDATA[<p>Long before I even started thinking about writing a blog covering the integration possibilities between Excel and Python, the boys at Simplistix (<a href="http://www.simplistix.co.uk">http://www.simplistix.co.uk</a>) were crafting some of the handiest Python modules around: xlrd, xlwt and xlutils.  These fantastic modules enable Python to directly read and write an Excel .xls file, without the need for Microsoft Excel.  Not only can you insert numbers and text, but xlwt supports a multitude of formatting options.  There&#8217;s even a great set of documentation, and a Google group monitored by the maintainers.  You can find out more about these modules at <a href="http://www.python-excel.org">http://www.python-excel.org</a></p>
<p>I&#8217;ve written a fair number of Python scripts that interface with Excel through the COM interface, but for many tasks you don&#8217;t need to invoke Excel to operate on spreadsheet data.  Although some advanced operations like charting and pivot tables are not currently supported, these utilities provide an excellent way of interfacing with Excel spreadsheets for many common jobs.</p>
<p>In my example below, I format a raw text file containing information on reference account categories for a hospital (based on data from <a href="http://www.data.gov">data.gov</a>):</p>
<pre class="brush: python; first-line: 78">
09700RESEARCH
09800PHYSICIANS  PRIVATE OFFICES
09900NONPAID WORKERS
MANAGEMENT FEES
REFERENCE LABS
</pre>
<p>The raw data is smashed together, with the account number and name running into each other without separation.  Some of the data doesn&#8217;t even have an account number at all.   The script accomplishes the following:</p>
<ul>
<li>Separate the account number and name, and write them into two separate columns in the spreadsheet</li>
<li>Assign an account number of 99999 for unnumbered accounts, and set the cell color to red</li>
<li>Convert the upper cased account name to a properly capitalized name, remove any extra spaces</li>
<li>Format the column width of each spreadsheet column based on the width of the data</li>
</ul>
<p>Based on the input above, the goal is to produce Excel output like this:</p>
<div id="attachment_53" class="wp-caption alignnone" style="width: 375px"><br />
<img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090910_1.PNG" alt="Excel output sample" title="20090910_1" width="365" height="119" class="size-full wp-image-53" /><br />
<p class="wp-caption-text">Excel output sample</p></div>
<p>Since there are no charts, pivot tables or other fancy formatting needed, xlwt is perfect for the job.  Here is the script that performs the conversion:</p>
<pre class="brush: python;">
#
#
import sys
import re
from xlwt import Workbook, easyxf

def doxl():
    '''Read raw account number and name strings, separate the data and
       write to an excel spreadsheet.  Properly capitalize the account
       names and mark cells with no account number as 99999 with red fill
       '''
    try:
        fp = open(&quot;hospdata.txt&quot;)
    except:
        print 'Failed to open hospdata.txt'
        sys.exit(1)
    lines = fp.readlines()

    nameandnum = re.compile(r'(\d+)\s*(.*)\s*')
    wb = Workbook()
    wsraw = wb.add_sheet('Raw Data')
    ws = wb.add_sheet('Account List')
    ws.write(0,0,'Account Number')
    ws.write(0,1,'Account Name')
    ws.col(0).width = len('Account Number') * 256
    ws.col(1).width = max([len(l) for l in lines]) * 256
    r = 1

    for line in lines:
        wsraw.write(r,0,line.strip())
        m = nameandnum.match(line)
        if m:
            ws.write(r,0,int(m.group(1)))
            ws.write(r,1,' '.join([w.capitalize() for w in m.group(2).split()]))
        else:
            ws.write(r,0,99999,easyxf('pattern: pattern solid, fore_colour red;'))
            ws.write(r,1,' '.join([w.capitalize() for w in line.split()]))
        r += 1
    wb.save('accounts.xls')
    print 'Wrote accounts.xls'

if __name__ == &quot;__main__&quot;:
    doxl()
</pre>
<p>Before running this example, you must have xlwt installed (please refer to the site <a href="http://www.python-excel.org">http://www.python-excel.org</a> for information on downloading and installing). Let&#8217;s look at the important bits in the script above.</p>
<p>The lines</p>
<pre class="brush: python; first-line: 12">
    try:
        fp = open("hospdata.txt")
    except:
        print 'Failed to open hospdata.txt'
        sys.exit(1)
    lines = fp.readlines()
</pre>
<p>attempt to open the file hospdata.txt.  If successful, the file contents are read into &#8220;lines&#8221; as a list of strings.  Next , the line</p>
<pre class="brush: python; first-line: 19">
    nameandnum = re.compile(r'(\d+)\s*(.*)\s*')
</pre>
<p>establishes a compiled regular expression used to parse each line and separate the account number and account name.  It&#8217;s assumed that the account numbers can only contain digits, and the account names cannot begin with a digit.  The compiled regular expression is used later to attempt a match on each line in the input file.</p>
<p>The following lines</p>
<pre class="brush: python; first-line: 20">
    wb = Workbook()
    wsraw = wb.add_sheet('Raw Data')
    ws = wb.add_sheet('Account List')
    ws.write(0,0,'Account Number')
    ws.write(0,1,'Account Name')
    ws.col(0).width = len('Account Number') * 256
    ws.col(1).width = max([len(l) for l in lines]) * 256
</pre>
<p>create a new workbook with two worksheets, &#8220;Raw Data&#8221; and &#8220;Account List&#8221;, which are used to store the unprocessed and processed data.  The headings &#8220;Account Number&#8221; and &#8220;Account Name&#8221; are written to the first row of the Account List worksheet.  To set the column width, the length of the longest string in each column is multiplied by 256 to calculate the setting.  Referring to the documentation for xlwt, you&#8217;ll see that the column width setting is based on the width of the 0 character for the first font in the list, not the default font, so you may want to fine tune the calculation to make the column width setting slightly wider than the actual data.</p>
<p>The next section iterates over each stored line from the text file.</p>
<pre class="brush: python; first-line: 29">
    for line in lines:
        wsraw.write(r,0,line.strip())
        m = nameandnum.match(line)
        if m:
            ws.write(r,0,int(m.group(1)))
            ws.write(r,1,' '.join([w.capitalize() for w in m.group(2).split()]))
        else:
            ws.write(r,0,99999,easyxf('pattern: pattern solid, fore_colour red;'))
            ws.write(r,1,' '.join([w.capitalize() for w in line.split()]))
</pre>
<p>The raw data is written to the Raw Data sheet, then the line is matched  against the regular expression.  If the match is successful, the number part is written to the first column, and the text is written to the second column.  The following statement in line 34:</p>
<pre class="brush: python; gutter: false;">
' '.join([w.capitalize() for w in m.group(2).split()])
</pre>
<p>splits account name information into individual words, capitalizes each word, then reassembles the string.  If you wanted to insert the account name string as-is, you would simply replace the statement above with</p>
<pre class="brush: python; gutter: false;">
m.group(2)
</pre>
<p>If no match occurs, then the string may not contain an account number and it is assumed that the whole string contains the account name only.  The dummy account number 99999 is inserted, and the cell background is changed to a red color.  This is done to flag the text for quick visual scanning.</p>
<p>After all input lines are processed, the accounts.xls file is written and a message is printed.</p>
<pre class="brush: python; first-line: 39">
wb.save('accounts.xls')
print 'Wrote accounts.xls'
</pre>
<p>The completed accounts.xls spreadsheet looks like this, with account number and name split into two columns and with a reformatted account name string:</p>
<div id="attachment_56" class="wp-caption alignnone" style="width: 411px"><img src="http://www.pythonexcels.com/wp-content/uploads/2009/09/20090910_2.png" alt="Snippet of the Excel file produced by above script" title="20090910_2" width="401" height="270" class="size-full wp-image-56" /><p class="wp-caption-text">Snippet of the Excel file produced by above script</p></div>
<p><strong>Prerequisites</strong><br />
Python (refer to <a href="http://www.python.org">http://www.python.org</a>)</p>
<p>xlwt (refer to <a href="http://www.python-excel.org">http://www.python-excel.org</a>)</p>
<p><strong>Source Files and Scripts</strong><br />
Source for the program and data text file are available at<br /><a href="http://github.com/pythonexcels/xlwt/tree/master">http://github.com/pythonexcels/xlwt/tree/master</a></p>
<p><strong>References</strong></p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.python-excel.org">http://www.python-excel.org</a></td>
<td>This site contains pointers to the best information available about working with Excel files in the Python programming language.</td>
</tr>
<tr>
<td><a href="http://groups.google.com/group/python-excel">http://groups.google.com/group/python-excel</a></td>
<td>Google group for questions on xlrd, xlwt, xlutils and general questions on interfacing to Excel with Python</td>
</tr>
</tbody>
</table>
<p>Thanks everyone &#8212; Dan</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/09/using-xlwt-to-write-spreadsheets-without-excel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Python</title>
		<link>http://www.pythonexcels.com/2009/07/installing-python/</link>
		<comments>http://www.pythonexcels.com/2009/07/installing-python/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 03:00:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.pythonexcels.com/?p=14</guid>
		<description><![CDATA[Getting started with Python is easy, you just need to download the python installation package and install onto your computer.  
Versions
As of this writing, Python 3.1 is the latest version, though I won’t be using the latest bleeding-edge build for my exercises.  There’s nothing wrong with 3.1, but third party package support for [...]]]></description>
			<content:encoded><![CDATA[<p>Getting started with Python is easy, you just need to download the python installation package and install onto your computer.  </p>
<p><strong>Versions</strong><br />
As of this writing, Python 3.1 is the latest version, though I won’t be using the latest bleeding-edge build for my exercises.  There’s nothing wrong with 3.1, but third party package support for the packages I use can trail the latest release by a version or two.   If you plan on installing third party libraries not provided in the standard Python release, you will want to use a slightly older version.  My exercises will be based on the latest Python 2.6.  </p>
<p><strong>Which Python foundation should I use? </strong><br />
There are different ways to obtain Python for the Windows platform.  Two of the most popular distributions are from the Python foundation and Activestate Software.   </p>
<p><strong>Python.org</strong><br />
The site <a href="http://www.python.org">http://www.python.org</a>, maintained by the Python Software Foundation, is the main portal for information on Python.  Python.org contains news, documentation, information on the latest releases, download source for current and previous versions of Python, and binary install files for Windows.  The latest version, as well as older versions of Python, can be found at <a href="http://www.python.org/download">http://www.python.org/download</a>.  This is the Python foundation that I typically use, the examples that follow will be based on Python 2.6.</p>
<p><strong>ActiveState Python</strong><br />
ActiveState Software provides software solutions for individuals and businesses, including a complete download package containing Python executables and documentation called ActivePython.   The package is non open source and available with an OEM license, which can be important in some corporate environments. Please refer to <a href="http://www.activestate.com/activepython">http://www.activestate.com/activepython</a> for more information. Python luminary Alex Martelli offers a concise description of Why ActiveState in this <a href="http://stackoverflow.com/questions/1352528/why-does-activepython-exist">StackOverflow post</a>.</p>
<p><strong>Build from Source</strong><br />
Source code for Python is available at <a href="http://www.python.org/download">http://www.python.org/download</a>, and while it is possible to create a working Python installation for Windows by compiling from source, it’s beyond the scope of these exercises.  </p>
<p><strong>Python Modules</strong><br />
One of the wonderful things about Python is the excellent library support for the language.  Python is “batteries included”: a large number of libraries are provided out-of-the-box, right in the standard distribution.  Other modules are available from a variety of sources, chances are you can find a module that helps you solve a problem with a simple web search.  I’ll use a variety of third party modules for the exercises that follow, but you’ll at least need to start with the pywin module.  You can find the appropriate pywin for your Python 2.6 installation at <a href="http://sourceforge.net/projects/pywin32/files">http://sourceforge.net/projects/pywin32/files</a> </p>
<p><strong>Resources</strong><br />
I won’t be covering the basics of Python, I suggest you check one of the many other resources.  The links listed on <a href="http://www.python.org/doc">http://www.python.org/doc</a> are an excellent starting point, many people also like the Dive into Python book at <a href="http://diveintopython.org">http://diveintopython.org</a>.  You can also find a number of other resources by searching for <a href="http://www.google.com/#hl=en&#038;q=learn+python">learn python</a>.  </p>
<p>Thanks &#8212; Dan  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.pythonexcels.com/2009/07/installing-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
