Package: xls-report
xls_reportDatabase report generation in xls-format according to the xml descriptionExample:#!/usr/bin/python3importsqlite3fromxls_reportimportXLSReportconnect=sqlite3.connect("chinook.sqlite")cursor=connect.cursor()report=XLSReport({'cursor':cursor,'xml':'test_xls.xml','callback_url':'http://localhost','callback_token':'12345','callback_frequency':20,'parameters':{'title0':'Invoices','customer':'','title1':'Albums','title2':'Money','title3':'Sales','title4':'Customers','artist':''}})report.to_file('test.xls')cursor.close()connect.close()test.xls:<?xml version='1.0' encoding='utf-8'?><book><report><name>{{title0}}</name><styledefname="Subheaders">font:boldTrue;alignment:horizcentre;borders:left1,top1,bottom1,right1;</styledef><styledefname="Totals">font:boldTrue;</styledef><styledefname="Fields">borders:left1,top1,bottom1,right1;</styledef><styledefname="Headers">font:boldTrue;alignment:horizcentre;</styledef><literalcol="0"row="0"stylename="Subheaders">Lastname</literal><literalcol="1"row="0"stylename="Subheaders">Firstname</literal><literalcol="2"row="0"stylename="Subheaders">Amount</literal><literalcol="3"row="0"stylename="Subheaders">Discount</literal><literalcol="4"row="0"stylename="Subheaders">Total</literal><sql><request>SELECTb.LastName,b.FirstName,round(sum(a.Total),2),round(sum(a.Total)/50,2)FROMInvoiceASaJOINCustomerASbON(b.CustomerId=a.CustomerId)WHEREb.LastNameLIKE'%{{customer}}%'GROUPBYb.LastName,b.FirstNameORDERBYb.LastName,b.FirstName;</request><groupstep="1"><fieldcol="0"name="Last name"header="no"row="1"stylename="Fields"/><fieldcol="1"name="First name"header="no"row="1"stylename="Fields"/><fieldcol="2"name="Amount"header="no"row="1"stylename="Fields"/><fieldcol="3"name="Discount"header="no"row="1"stylename="Fields"/></group><formulacol="4"name="Total"row="1"header="no"stylename="Fields"format="0.00">C{{cs}}-D{{cs}}</formula></sql><sql><literalcol="0"row="1"stylename="Totals">Total:</literal><formulacol="4"name="Total"row="1"header="no"stylename="Totals"format="0.00">SUM(E2:E{{ds}})</formula></sql></report><report><name>{{title1}}</name><literalcol="0"row="0"stylename="Subheaders">Artist</literal><literalcol="1"row="0"stylename="Subheaders">Album</literal><sql><request>SELECTb.nameasArtist,a.TitleasAlbumFROMAlbumaJOINArtistbON(b.ArtistId=a.ArtistId)WHEREArtistLIKE'%{{artist}}%'ORDERBYArtist,Title;</request><groupstep="1"><fieldcol="0"name="Artist"header="no"row="1"width="20000"stylename="Fields"/><fieldcol="1"name="Album"header="no"row="1"width="20000"stylename="Fields"/></group></sql></report><report><name>{{title2}}</name><literalcol="0"row="0"stylename="Headers">Reportbysomegenres</literal><literalcol="0"row="2"stylename="Headers">Media</literal><literalcol="1"row="2"stylename="Headers">Genre</literal><literalcol="2"row="2"stylename="Headers">Amount</literal><literalcol="3"row="2"stylename="Headers">Discount</literal><literalcol="4"row="2"stylename="Headers">Charged</literal><sql><request>SELECTd.NameASMedia,round(sum(a.Quantity*a.UnitPrice),2)ASMoney,round(sum(a.Quantity*a.UnitPrice/50),2)ASDiscountFROMInvoiceLineASaJOINTrackASbON(b.TrackId=a.TrackId)JOINGenreAScON(c.GenreId=b.GenreId)JOINMediaTypeasdON(d.MediaTypeId=b.MediaTypeId)WHEREc.Name='Latin'GROUPBYd.Name,c.NameORDERBYd.Name,c.Name</request><groupstep="4"><fieldcol="0"name="Media"header="no"row="3"width="7000"/><fieldcol="2"name="Money"header="no"row="3"/><fieldcol="3"name="Discount"header="no"row="3"/><groupliteralcol="1"name="Type"row="3"header="no">Latin</groupliteral><formulacol="4"name="Total"row="3"header="no">C{{cs}}-D{{cs}}</formula></group></sql><sqlcycle="yes"><request>SELECTround(sum(a.Quantity*a.UnitPrice),2)ASMoney,round(sum(a.Quantity*a.UnitPrice/50),2)ASDiscountFROMInvoiceLineASaJOINTrackASbON(b.TrackId=a.TrackId)JOINGenreAScON(c.GenreId=b.GenreId)JOINMediaTypeasdON(d.MediaTypeId=b.MediaTypeId)WHEREc.Name='World'GROUPBYd.Name,c.NameORDERBYd.Name,c.Name</request><groupstep="4"><fieldcol="2"name="Money"header="no"row="4"/><fieldcol="3"name="Discount"header="no"row="4"/><groupliteralcol="1"name="Type"row="4"header="no">World</groupliteral><formulacol="4"name="Total"row="4"header="no">C{{cs}}-D{{cs}}</formula></group></sql><sqlcycle="yes"><groupstep="4"><groupliteralcol="0"name="Type"row="5"header="no"stylename="Totals">Subtotal:</groupliteral><formulacol="4"name="Total"row="5"header="no"stylename="Totals"cycle="2">INDIRECT("E"&amp;({{ss}}+3))+INDIRECT("E"&amp;({{ss}}+4))</formula></group></sql><sql><literalcol="0"row="0"stylename="Totals">Total:</literal><formulacol="4"name="Total"row="0"header="no"stylename="Totals"format="0.00">INDIRECT("E"&amp;({{cs}}-5))+INDIRECT("E"&amp;({{cs}}-1))</formula></sql></report><report><name>{{title3}}</name><literalcol="0"row="0"stylename="Subheaders">Media</literal><literalcol="1"row="0"stylename="Subheaders">Genre</literal><literalcol="2"row="0"stylename="Subheaders">Amount</literal><literalcol="3"row="0"stylename="Subheaders">Discount</literal><literalcol="4"row="0"stylename="Subheaders">Charged</literal><sql><requestsuppress="Media"skip="2"skip_totals="2"subtotal="Money, Discount, Charged"total="Money, Discount, Charged">SELECTd.NameASMedia,c.NameasGenre,round(sum(a.Quantity*a.UnitPrice),2)ASMoney,round(sum(a.Quantity*a.UnitPrice/50),2)ASDiscount,round(sum(a.Quantity*a.UnitPrice),2)-round(sum(a.Quantity*a.UnitPrice/50),2)ASChargedFROMInvoiceLineASaJOINTrackASbON(b.TrackId=a.TrackId)JOINGenreAScON(c.GenreId=b.GenreId)JOINMediaTypeasdON(d.MediaTypeId=b.MediaTypeId)GROUPBYd.Name,c.NameORDERBYd.Name,c.Name</request><groupstep="1"><fieldcol="0"name="Media"header="no"row="1"width="7000"stylename="Fields"/><fieldcol="1"name="Genre"header="no"row="1"width="5000"stylename="Fields"/><fieldcol="2"name="Money"header="no"row="1"format="0.00"stylename="Fields"/><fieldcol="3"name="Discount"header="no"row="1"format="0.00"stylename="Fields"/><fieldcol="4"name="Charged"header="no"row="1"format="0.00"stylename="Fields"/></group></sql></report><report><name>{{title4}}</name><literalcol="0"row="0"stylename="Subheaders">Customer</literal><literalcol="1"row="0"stylename="Subheaders">Media</literal><literalcol="2"row="0"stylename="Subheaders">Genre</literal><literalcol="3"row="0"stylename="Subheaders">Amount</literal><literalcol="4"row="0"stylename="Subheaders">Discount</literal><literalcol="5"row="0"stylename="Subheaders">Charged</literal><sql><requestsuppress="Customer, Media"skip="2"skip_totals="2"subtotal="Money, Discount, Charged"total="Money, Discount, Charged">SELECTf.LastName||''||f.FirstNameASCustomer,d.NameASMedia,c.NameasGenre,round(sum(a.Quantity*a.UnitPrice),2)ASMoney,round(sum(a.Quantity*a.UnitPrice/50),2)ASDiscount,round(sum(a.Quantity*a.UnitPrice),2)-round(sum(a.Quantity*a.UnitPrice/50),2)ASChargedFROMInvoiceLineASaJOINTrackASbON(b.TrackId=a.TrackId)JOINGenreAScON(c.GenreId=b.GenreId)JOINMediaTypeasdON(d.MediaTypeId=b.MediaTypeId)JOINInvoiceaseON(e.InvoiceId=a.InvoiceId)JOINCustomerasfON(f.CustomerId=e.CustomerId)WHEREf.LastNameLIKE'%%'GROUPBYCustomer,d.Name,c.NameORDERBYCustomer,d.Name,c.Name</request><groupstep="1"><fieldcol="0"name="Customer"header="no"row="1"width="5000"stylename="Fields"/><fieldcol="1"name="Media"header="no"row="1"width="7000"stylename="Fields"/><fieldcol="2"name="Genre"header="no"row="1"width="5000"stylename="Fields"/><fieldcol="3"name="Money"header="no"row="1"format="0.00"stylename="Fields"/><fieldcol="4"name="Discount"header="no"row="1"format="0.00"stylename="Fields"/><fieldcol="5"name="Charged"header="no"row="1"format="0.00"stylename="Fields"/></group></sql></report><report><name>Playlist</name><literalcol="0"row="0"stylename="Subheaders">Playlist</literal><literalcol="1"row="0"stylename="Subheaders">Album</literal><literalcol="2"row="0"stylename="Subheaders">Track</literal><literalcol="3"row="0"stylename="Subheaders">Milliseconds</literal><literalcol="4"row="0"stylename="Subheaders">Bytes</literal><literalcol="5"row="0"stylename="Subheaders">Price</literal><sql><requestsuppress="Playlist, Album"skip="2"skip_totals="2"subtotal="Milliseconds, Bytes, Price"total="Milliseconds, Bytes, Price">SELECTDISTINCTb.NameASPlaylist,d.TitleASAlbum,c.NameASTrack,c.Milliseconds,c.Bytes,c.UnitPriceASPriceFROMPlaylistTrackasaJOINPlaylistasbON(b.PlaylistId=a.PlaylistId)JOINTrackascON(c.TrackId=a.TrackId)JOINAlbumasdON(d.AlbumId=c.AlbumId)ORDERBYb.Name,d.Title,c.Name</request><groupstep="1"><fieldcol="0"name="Playlist"header="no"row="1"width="5900"stylename="Fields"/><fieldcol="1"name="Album"header="no"row="1"width="20500"stylename="Fields"/><fieldcol="2"name="Track"header="no"row="1"width="20000"stylename="Fields"/><fieldcol="3"name="Milliseconds"header="no"row="1"width="5000"stylename="Fields"/><fieldcol="4"name="Bytes"header="no"row="1"width="5000"stylename="Fields"/><fieldcol="5"name="Price"header="no"row="1"progress="yes"width="5000"format="0.00"stylename="Fields"/></group></sql></report></book>See directory test. TODO: normal documentation.