Django - format excel cells while exporting excel - python

I am trying to perform excel export functionality in Django in which I am generating an excel file as per the selection of field list. In that, I want to format cells as per the field data. Currently, data for a date is not showing in the proper date format. I am attaching a screenshot for the same.
Date format not proper
Every time after downloading excel I need to change the cell format manually.
Format change mannually
But I want to set the format for the date field via code.
Here is my code for generating excel and downloading it.
checkedField = request.POST.getlist('excelfields[]')
FinalPath = ''
filename = 'media\ExcelExportClientReg\InitalRegistaration.xls'
work_book = xlwt.Workbook(encoding='utf-8')
uc = u"".join(chr(0x0410 + i) for i in range(32)) # some Cyrillic characters
u8 = uc.encode("UTF-8")
work_sheet = work_book.add_sheet('Client Registration')
style_head_row = xlwt.easyxf("""
align:
wrap off,
vert center,
horiz center;
borders:
left THIN,
right THIN,
top THIN,
bottom THIN;
font:
name Arial,
colour_index white,
bold on,
height 0xA0;
pattern:
pattern solid,
fore-colour 0x15;
"""
)
style_data_row = xlwt.easyxf("""
align:
wrap on,
vert center,
horiz left;
font:
name Arial,
bold off,
height 0XA0;
borders:
left THIN,
right THIN,
top THIN,
bottom THIN;
"""
)
# set columns value.
row_num = 0
columns = checkedField
for col_num in range(len(columns)):
work_sheet.write(row_num, col_num, columns[col_num],style_head_row)
# set rows value
if request.session['AdminID'] == 1:
rows = ClientRegistration.objects.values_list(*checkedField).all()
else:
rows = ClientRegistration.objects.values_list(*checkedField).filter(CreatedBy=request.session['AdminID'],IsDeleted=0)
for row in rows:
row_num += 1
for col_num in range(len(row)):
work_sheet.write(row_num, col_num, row[col_num],style_data_row)
work_book.save(filename)
FinalPath = os.path.join(settings.BASE_DIR,filename)
path = open(FinalPath, 'rb')
mime_type, _ = mimetypes.guess_type(FinalPath)
response = HttpResponse(path,content_type=mime_type)
response['Content-Disposition'] = 'attachment; filename="InitalRegistaration.xls"'
os.remove(FinalPath)
return response
Here checkedField is the checkbox value for which fields need to add to the excel file.
Please help me with this. Thank you in advance.

Related

Pandas table customization

This is a section of my python code, this class retrieves a sheet from smartsheet and turns it into a df, which later uses to display on a table on my GUI. I've been trying to change row colors but cant seem to get it right, in the code I managed to change the color of columns, however when I pass self.table.rowcolors... it does nothing. Anyone has an idea of what else I could try?
class SmartsheetFrame(Frame):
def __init__(self, master):
super().__init__(master)
self.configure(bg='white')
# Get the sheet
sheet_id = 3839061875025796
ss_client = smartsheet.Smartsheet(access_token=os.environ.get('SMARTSHEET_ACCESS_TOKEN'))
sheet = ss_client.Sheets.get_sheet(sheet_id)
rows = sheet.rows
columns = sheet.columns
#Creating a dataframe from the sheet
df = pd.DataFrame(columns=[col.title for col in columns])
for row in rows:
df.loc[row.id] = [col.value for col in row.cells]
last_4_rows = df.tail(4)
# Create a Table widget and set its properties
self.table = pt.Table(self, dataframe=df, showstatusbar=True, height=600, width=1200)
# Specify the row index you want to color
self.table.columncolors['AEM ID'] = 'forestgreen'
self.table.columncolors['Intel ID'] = 'midnightblue'
self.table.columncolors['Site'] = 'darkslategrey'
self.table.columncolors['Mode'] = 'firebrick'
self.table.redraw()
self.table.show()
I've tried many methods that I found online, so far I've managed to chage the color of columns, but havent been able to do the same for rows

Folium - add larger pop ups with data from XML file

I would like to create a table-like pop-up for my folium map but don't know how to do it (I'm a novice).
My data comes from an XML file that contains the gps coordinates, name, sales, etc. of stores.
Right now I can display the name of the stores in the pop-up, but I would also like to display the sales and other information below the name.
I reckon I should maybe use GeoJson but I don't know how to implement it in the code I already have (which contains clusterization) :
xml_data = 'Data Stores.xml'
tree = ElementTree.parse(xml_data)
counter = tree.find('counter')
name = counter.find('Name')
counter.find('Latitude').text
name = []
latitude = []
longitude = []
for c in tree.findall('counter'):
name.append(c.find('Name').text)
latitude.append(c.find('Latitude').text)
longitude.append(c.find('Longitude').text)
df_counters = pd.DataFrame(
{'Name' : name,
'Latitude' : latitude,
'Longitude' : longitude,
})
df_counters.head()
locations = df_counters[['Latitude', 'Longitude']]
locationlist = locations.values.tolist()
map3 = folium.Map(location=[31.1893,121.2781], tiles='CartoDB positron', zoom_start=6)
marker_cluster = folium.plugins.MarkerCluster().add_to(map3)
for point in range(0, len(locationlist)):
popup=folium.Popup(df_counters['Name'][point], max_width=300,min_width=300)
folium.Marker(locationlist[point],
popup=popup,
icon=folium.Icon(color='blue', icon_color='white',
icon='fa-shopping-bag', angle=0, prefix='fa')
).add_to(marker_cluster)
map3.save("WorldMap.html")`
Right now I have 4 other columns in my XML file besides 'Name' that have the information that I want to appear in the popup as well, kinda like this :
example popup
Thank you for your help
Edit :
I did some digging and changed my code a little bit by adding the folium.features.GeoJsonPopup instead of the simple folium.Popup that I had before :
for point in range(0, len(locationlist)):
popup=folium.features.GeoJsonPopup(
fields=[['Name'],['Opening']],
aliases=['Name','Opening'])
folium.Marker(locationlist[point],
popup=popup,
icon=folium.Icon(color='blue', icon_color='white',
icon='fa-shopping-bag', angle=0, prefix='fa')
).add_to(marker_cluster)
I added the 'Opening' data, however I don't know how to transfer it into the pop up along with the 'Name' since it comes from a panda DataFrame. Right now my popups are empty.
I have done something similar, steps were:
create an IFrame with the content you want to display (coded in HTML)
use this IFrame in a popup
connect this popup with your marker
htmlstr = ... # Here you can add your table, use HTML
# 1. iframe
iframe = folium.IFrame(htmlstr, # places your content in the iframe
width=200,
height=200 # adjust size to your needs
)
# 2. popup
fpop = folium.Popup(iframe)
# 3. marker
mrk = folium.Marker(location=latlng,
popup=fpop,
)
mrk.add_to( ... )

How to ignore table and its content while extracting text from pdf

So far I am successful extracting the text content from a pdf file. I am stuck to a point where i have to extract text content outside of the table (ignore table and its content) and need help
The Pdf can be downloaded from here
import pdfplumber
pdfinstance = pdfplumber.open(r'\List of Reportable Jurisdictions for 2020 CRS information reporting_9 Feb.pdf')
for epage in range(len(pdfinstance.pages)):
page = pdfinstance.pages[epage]
text = page.extract_text(x_tolerance=3, y_tolerance=3)
print(text)
For the PDF you have shared, you can use the following code to extract the text outside the tables
import pdfplumber
def not_within_bboxes(obj):
"""Check if the object is in any of the table's bbox."""
def obj_in_bbox(_bbox):
"""See https://github.com/jsvine/pdfplumber/blob/stable/pdfplumber/table.py#L404"""
v_mid = (obj["top"] + obj["bottom"]) / 2
h_mid = (obj["x0"] + obj["x1"]) / 2
x0, top, x1, bottom = _bbox
return (h_mid >= x0) and (h_mid < x1) and (v_mid >= top) and (v_mid < bottom)
return not any(obj_in_bbox(__bbox) for __bbox in bboxes)
with pdfplumber.open("file.pdf") as pdf:
for page in pdf.pages:
print("\n\n\n\n\nAll text:")
print(page.extract_text())
# Get the bounding boxes of the tables on the page.
bboxes = [
table.bbox
for table in page.find_tables(
table_settings={
"vertical_strategy": "explicit",
"horizontal_strategy": "explicit",
"explicit_vertical_lines": page.curves + page.edges,
"explicit_horizontal_lines": page.curves + page.edges,
}
)
]
print("\n\n\n\n\nText outside the tables:")
print(page.filter(not_within_bboxes).extract_text())
I am using the .filter() method provided by pdfplumber to drop any objects that fall inside the bounding box of any of the tables (in not_within_bboxes(...)) and creating a filtered version of the page which will only contain those objects that fall outside any of the tables.

How do I convert a spreadsheet read with OpenPyXL into XlsxWriter?

TL; DR
How do I load a spreadsheet template using OpenPyXL
workbook = openpyxl.load_workbook('template.xlsx')
then create a new one and fill the rows data with XlsxWriter?
xls_workbook = xlsxwriter.Workbook('proposal.xlsx')
# Missing step
xls_workbook = workbook.add_worksheet(workbook)
xls_workbook.write(CELL_COST, cost)
Details
I have a spreadsheet with several tabs with a quite complex formatting (used as a sales proposal), so there is a lot of formatting that must be preserved.
So, instead of programatically create the spreadsheet, I have to:
Open the template for reading using OpenPyXL
Extract the template and save it into a template.py file
Create the sales pitch spreadsheets using the template, creating new tables with XlsxWriter.
Is there a simple way of extracting the template or do really I need recreate the whole layout programmatically?
I have run into the same "problem" and have not found much about it. So finally I code a little function to copy the template sheet and some styling.
It's 2 years late but I hope it helps someone who comes to this question.
def openpyxl_to_xlsxwriter(openpyxl_workbook, xlsxwriter_workbook):
template_sheets = openpyxl_workbook.get_sheet_names()
# Copy all the sheets from the openpyxl template to the xlsxwriter workbook.
for sheet_name in template_sheets:
xlsxwriter_workbook.add_worksheet(sheet_name)
for sheet in template_sheets:
openpyxl_active_sheet = openpyxl_workbook.get_sheet_by_name(sheet)
xlsxwriter_active_sheet = xlsxwriter_workbook.get_worksheet_by_name(sheet)
for row in openpyxl_active_sheet.rows:
for cell in row:
# # Copy some STYLES # #
# Copy font color and Background color
cell_style = {}
theme = cell.fill.start_color.theme
tint = cell.fill.start_color.tint
font_theme = cell.font.color.theme
font_tint = cell.font.color.tint
font_color = theme_and_tint_to_rgb(openpyxl_workbook, font_theme, font_tint)
cell_style['font_color'] = font_color
try:
background_color = theme_and_tint_to_rgb(openpyxl_workbook, theme, tint)
cell_style['bg_color'] = background_color
except:
pass
cell_format = xlsxwriter_workbook.add_format(cell_style)
# Copy border
border_left = cell.border.left.border_style
border_right = cell.border.right.border_style
border_top = cell.border.top.border_style
border_bottom = cell.border.bottom.border_style
if border_left:
cell_format.set_left()
if border_right:
cell_format.set_right()
if border_top:
cell_format.set_top()
if border_bottom:
cell_format.set_bottom()
# Copy Cell Width and Height
cell_height = openpyxl_active_sheet.row_dimensions[cell.row].height
cell_width = openpyxl_active_sheet.column_dimensions[cell.column_letter].width
column_index = cell.column - 1
xlsxwriter_active_sheet.set_column(column_index, column_index, cell_width)
row_index = cell.row - 1
xlsxwriter_active_sheet.set_row(row_index, cell_height)
# Copy Cell Value
xlsxwriter_active_sheet.write(cell.coordinate, cell.value, cell_format)

multiple value from mysql to reportlab

i have an issue that i can't show my second record in mysql table. The report just showing 1 record in a row and the second one isn't show on pdf file. i'm using reportlab for report generator on python 2.7
this is my code that i can' fix yet :
def nilaisql():
rpt = raw_input("input NPM : ")
sql = "select nama, tanggal, jamMasuk from t_"+rpt
curs.execute(sql)
result = curs.fetchall()
for row in result:
c = canvas.Canvas("Sampelone.pdf")
c.drawString(250, 700, str(row[0]))
c.save()
os.system("Sampelone.pdf")
this is my record on mysql. I want to show the second row record but the pdf just showing the first row record
it should showing the second row record
and this is the result on my pdf file
i'm getiing stuck in here and if you know something i'm really grateful that you can share the solution in here
for row in result:
c = canvas.Canvas("Sampelone.pdf")
c.drawString(250, 700, str(row[0]))
c.save()
what your code snippet is doing is, creating a new file and writing the content of your variable row into the pdf file and c.save saves it. In the next iteration, this same file is recreated which is blank and the original file is overwritten by this blank file and the content of row is printed that is why you will always see only first row record in it.
This should work fine. Increment or Decrement the value of y according to your use and document height.
c = canvas.Canvas("Sampelone.pdf") #creates a pdf
for row in result:
c.drawString(250, y, str(row[0])) #writes data at given co-ordinates
c.save() #saves the pdf
This way you can see all row records in the pdf.
But this practice is not considered good, you should always put your data in flowable like this. .
from reportlab.lib import styles
from reportlab.platypus import SimpleDocTemplate, Paragraph
def nilaisql():
pdfname = 'mydoc.pdf'
doc = SimpleDocTemplate(
pdfname
)
style = styles["Normal"]
story = []
rpt = raw_input("input NPM : ")
sql = "select nama, tanggal, jamMasuk from t_" + rpt
curs.execute(sql)
result = curs.fetchall()
for row in result:
story.append(Paragraph(row, style))
doc.build(
story
)
os.system("Sampelone.pdf")
Read more about flowables in reportlab-userguide

Categories