Unable to write image in PDF File - python

def logo_para(self):
exp = Paragraph(
'<b>Express</b>', self.styles['CenterHeading'])
csheet = Paragraph(
'<b>PDF SHEET</b>', self.styles['CenterHeading'])
img_location = "https://www.google.co.in/logos/doodles/2016/icc-australia-v-bangladesh-5759441086447616-res.png"
img_data = '''
<para><img src="%s" width="300" height="90"/><br/>
</para>''' % img_location
img = Paragraph(img_data, self.styles['CenterHeading'])
data = [[exp], [csheet], [''], [img] ]
main_header_table = Table([['', img, '']], colWidths=(100, 300, 100))
main_header_table.setStyle(TableStyle([
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('BOX', (0, 0), (-1, -1), 0.25, colors.black)
]))
self.elements.append(main_header_table)
When ever I am calling
docket.logo_para()
I am getting error cannot concatenate 'str' and 'int' objects
at self.doc.build(self.elements)
When the line is commenteddocket.logo_para(), the code works superbly.
I am trying to add an image on the PDF File using SimpleDocTemplate
EDIT 1
creating new pdf
class PDFDocketGenerator(object):
def __init__(self, file_name):
self.filename = file_name
self.filepath = STATIC_URL + 'uploads/billing/' + file_name
self.path_to_save = FILE_UPLOAD_TEMP_DIR + '/billing/' + file_name
# define the pdf object
self.doc = SimpleDocTemplate(
self.path_to_save, pagesize=landscape(A4), topMargin=50, bottomMargin=30,
leftMargin=60, rightMargin=60)
self.elements = []
writing to pdf
def write_pdf(self):
self.doc.build(self.elements)

Is it possible that some values in self.elements are integers? I would suggest to try this in this case :
def write_pdf(self):
self.doc.build([str(e) for e in self.elements])

Related

Python Reportlab - Wordwrap on Table is splitting words rather than at spaces

I created a PDF in reportlab using a canvas:
self.pdf = canvas.Canvas(f'{file_name}.pdf', pagesize=A4)
I create tables within tables to create my document but one of my tables is not wrapping the way I expect it to. Rather than linebreaking at spaces, it does so between words as seen below.
The code below is the code I used to create the table. It is a bit long as I did make sure that the cells I'm passing into the Table() are all Paragraph().
def _discount_table(self, width_list):
# Table Name
table_name = Paragraph('DISCOUNTS', self.header_style_grey)
# Create Header
header = [Paragraph('NAME', self.table_header_style_left)]
header += [Paragraph(x, self.table_header_style_right) for x in self.unique_discount_list]
header += [Paragraph('TOTAL', self.table_header_style_right)]
# Process Data
discount_data = [[Paragraph(cell, self.table_style2) for cell in row] for row in self.discount_data]
data = [[child_row[0]] + disc for child_row, disc in zip(self.fees_data, discount_data)]
# Create Footer
table_footer = [Paragraph('') for _ in range(len(header) - 2)]
table_footer += [Paragraph('TOTAL', self.table_header_style_right),
Paragraph(f'{self.discount_total:,.2f}', self.table_header_style_right)]
# Create Table
bg_color = self.header_style_grey.textColor
table = Table([header] + data + [table_footer], colWidths=width_list)
table.setStyle([
('GRID', (0, 0), (-1, -1), 1, 'black'),
('BACKGROUND', (0, 0), (-1, 0), bg_color),
('TEXTCOLOR', (0, 0), (-1, 0), 'white'),
('BACKGROUND', (-2, -1), (-1, -1), bg_color),
('TEXTCOLOR', (-2, -1), (-1, -1), 'white'),
('FONTNAME', (-2, -1), (-1, -1), 'Helvetica-Bold'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
('ROWBACKGROUNDS', (0, 1), (-1, -2), ['lightgrey', 'white']),
])
return [table_name, table]
(To note that child_row[0] is already a Paragraph - this is found on the line 12 above)
The styling I used is imported from another python file as follows:
self.table_style2 = ParagraphStyle('table_style')
self.table_style2.wordWrap = 'CJK'
self.table_style2.alignment = TA_RIGHT
self.table_style = ParagraphStyle('table_style')
self.table_style.wordWrap = 'CJK'
self.table_header_style_right = ParagraphStyle('table_header_style', self.table_style)
self.table_header_style_right.textColor = colors.HexColor('#FFFFFF')
self.table_header_style_right.fontName = 'Helvetica-Bold'
self.table_header_style_right.alignment = TA_RIGHT
self.table_header_style_right.wordWrap = 'CJK'
self.table_header_style_left = ParagraphStyle('table_header_style', self.table_style)
self.table_header_style_left.textColor = colors.HexColor('#FFFFFF')
self.table_header_style_left.fontName = 'Helvetica-Bold'
self.table_header_style_left.wordWrap = 'CJK'
So I am really lost and need help. Why is the table not wrapping correctly?
I was able to fix the table wrap issue when I removed the wordWrap = 'CJK' portion of the code. I saw in a video that a Paragraph() will automatically wordWrap so I'm guessing there was some issue with how those two elements overlap
self.table_style2 = ParagraphStyle('table_style')
# self.table_style2.wordWrap = 'CJK'
self.table_style2.alignment = TA_RIGHT
self.table_style = ParagraphStyle('table_style')
# self.table_style.wordWrap = 'CJK'
self.table_header_style_right = ParagraphStyle('table_header_style', self.table_style)
self.table_header_style_right.textColor = colors.HexColor('#FFFFFF')
self.table_header_style_right.fontName = 'Helvetica-Bold'
self.table_header_style_right.alignment = TA_RIGHT
# self.table_header_style_right.wordWrap = 'CJK'
self.table_header_style_left = ParagraphStyle('table_header_style', self.table_style)
self.table_header_style_left.textColor = colors.HexColor('#FFFFFF')
self.table_header_style_left.fontName = 'Helvetica-Bold'
# self.table_header_style_left.wordWrap = 'CJK'

reportlab use for loop to create multiple tables

I need through a for loop to create more tables, I think it works but I need to change the various coordinates, how can I do?
2)
Is it possible to change the width of a single row of a table? or in any case bring its text-align to the left but which starts from where the table starts?
def testPdfView(request, id):
#dati init
scheda = get_object_or_404(Schede, pk = id)
filename = 'media/pdf/' + scheda.nome_scheda + '.pdf'
titolo = scheda.utente.username + ' - ' + scheda.nome_scheda
#creazione file
doc = SimpleDocTemplate(
filename,
pagesize = A4,
rightMargin = 10*mm,
leftMargin = 10*mm,
topMargin = 47*mm,
bottomMargin = 10*mm
)
#titolo
doc.title = titolo
#passaggio scheda alla funzione pdfCanvas
doc.scheda = scheda
#table gruppi
gruppi = DatiGruppi.objects.filter(gruppi_scheda = id)
for gruppo in gruppi:
table = Table([
[str(gruppo).upper()]
], colWidths= 180*mm, repeatRows=1)
#table style
style = TableStyle([
('TEXTCOLOR', (0,0),(-1,0), colors.HexColor("#9FFC0D")),# -1 significa l'ultimo elemento
('FONTNAME', (0,0), (0,0), 'bulk_bold'),
('FONTSIZE', (0,0), (0,0), 6*mm),
('BOTTOMPADDING', (0,0), (-1,0), 6*mm),
('LINEBELOW',(0,0),(-1,0), 1, colors.HexColor("#9FFC0D")),
])
table.setStyle(style)
#table add to template
elems = []
elems.append(table)
#create
doc.build(elems, onFirstPage = pdfCanvas)
def genGroupTable(gruppo):
groupElemTeble = None
#tab
titleTable = Table([
[str(gruppo).upper(), str(gruppo.giorni_settimana).upper()]
], colWidths= 95*mm)
titleTable_style = TableStyle([
('TEXTCOLOR', (0,0),(-1,0), colors.HexColor("#9FFC0D")),
('FONTNAME', (0,0), (0,0), 'bulk_bold'),
('ALIGN',(1,0),(-1,0),'RIGHT'),
('VALIGN',(0,0),(-1,0),'MIDDLE'),
('FONTSIZE', (0,0), (0,0), 6*mm),
('BOTTOMPADDING', (0,0), (0,0), 6*mm),
('LINEBELOW',(0,0),(-1,0), 1, colors.HexColor("#9FFC0D")),
('LEFTPADDING',(0,0),(-1,-1), 0*mm),
('RIGHTPADDING',(0,0),(-1,-1), 0*mm)
])
titleTable.setStyle(titleTable_style)
thead = Table([
['ESERCIZIO','SERIE','RIPETIZIONI','PESO']
], colWidths= 47.5*mm)
thead_style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#19212A")),
('TEXTCOLOR', (0,0),(-1,0), colors.HexColor("#ffffff")),
('FONTNAME', (0,0), (-1,0), 'bulk_testo'),
('ALIGN',(0,0),(-1,0),'CENTER'),
('VALIGN',(0,0),(-1,0),'MIDDLE'),
('BOTTOMPADDING', (0,0), (-1,0), 1*mm)
])
thead.setStyle(thead_style)
exercise = []
elementi = []
for esercizio in gruppo.gruppo_single.all():
exercise.append(esercizio)
for es in range(len(exercise)):
tbody = Table([
[str(exercise[es]).upper(), str(exercise[es].serie).upper(), str(exercise[es].ripetizione).upper(), str(exercise[es].peso).upper()+'KG']
], colWidths= 47.5*mm)
tbody_style = TableStyle([
('TEXTCOLOR', (0,0),(-1,-1), colors.HexColor("#ffffff")),
('FONTNAME', (0,0), (-1,-1), 'bulk_testo'),
('ALIGN',(0,0),(-1,-1),'CENTER'),
('BOTTOMPADDING', (0,0), (-1,-1), 1*mm),
('LINEBELOW',(0,0),(-1,-1), .2, colors.HexColor("#ffffff"))
])
tbody.setStyle(tbody_style)
elementi.append(tbody)
#tab finale
groupElemTeble = Table([
[titleTable],
[thead],
[[elementi]]
], colWidths = 190*mm)
groupElemTeble_style = TableStyle([
#('BACKGROUND', (0, 0), (-1, -1), colors.HexColor("#202B38")),
('LEFTPADDING',(0,0),(-1,-1), 0*mm),
('RIGHTPADDING',(0,0),(-1,-1), 0*mm),
('BOTTOMPADDING',(-1,-1),(-1,-1), 5*mm)
])
groupElemTeble.setStyle(groupElemTeble_style)
return groupElemTeble
def testPdfView(request, id):
#dati init
scheda = get_object_or_404(Schede, pk = id)
filename = 'media/pdf/' + scheda.nome_scheda + '.pdf'
titolo = scheda.utente.username + ' - ' + scheda.nome_scheda
#creazione file
doc = SimpleDocTemplate(
filename,
pagesize = A4,
rightMargin = 10*mm,
leftMargin = 10*mm,
topMargin = 47*mm,
bottomMargin = 10*mm
)
#titolo
doc.title = titolo
#passaggio scheda alla funzione pdfCanvas
doc.scheda = scheda
#elemento vuoto
elems = []
#lista gruppi
group = []
gruppi = DatiGruppi.objects.filter(gruppi_scheda = id)
for gruppo in gruppi:
group.append(gruppo)
for gr in range(len(group)):
main = genGroupTable(group[gr])
elems.append(main)
#create
doc.multiBuild(elems, onFirstPage = header)
#return
percorso = str(settings.BASE_DIR) +'/media/pdf/' + scheda.nome_scheda + '.pdf'
return FileResponse(open(percorso, 'rb'), content_type='application/pdf')

self.attribute error when changing from function to class

New to python and coding in general.. Not sure why the code is throwing this error:
File "c:\Users...\Python Projects\Trials\Trial 4\findClickPositions.py", line 18, in findclickpositions
AttributeError: 'numpy.ndarray' object has no attribute 'needle_img_path'
Line 18 being:
self.needle_img_path = str("./Trees/" + str(Tree) + ".png")
Here's the full code:
import cv2 as cv
import numpy as np
import os
from random import randint
from windowcapture import Windowcapture
from time import time
class find_object:
def __init__(self):
self.whatami = []
self.needle_img_path = str("")
def findclickpositions(self, img, Tree='tree', threshold=0.95, debug_mode=None):
os.makedirs('Trees', exist_ok=True)
self.needle_img_path = str("./Trees/" + str(Tree) + ".png")
self.treeimage = cv.imread(self.needle_img_path, cv.IMREAD_REDUCED_COLOR_2)
if not self.treeimage:
raise Exception('Image file of requested tree not found')
self.needle_img = cv.imread(self.needle_img_path, cv.IMREAD_REDUCED_COLOR_2)
self.method = cv.TM_CCOEFF_NORMED
self.result = cv.matchTemplate(self.img, self.needle_img, self.method)
#cv.imshow('Result', result)
#cv.waitKey()
self.min_val, self.max_val, self.min_loc, self.max_loc = cv.minMaxLoc(self.result) #gets the best match position
#print('Best match top left postion: %s' % str(max_loc))
#print('Best match confidence: %s' % str(max_val))
self.locations = np.where(self.result >=self.threshold)
self.locations = list(zip(*self.locations[::-1]))
#print(locations)
self.needle_w = self.needle_img.shape[1]
self.needle_h = self.needle_img.shape[0]
self.rectangles = []
for self.loc in self.locations:
self.rect = [int(loc[0]), int(self.loc[1]), self.needle_w, self.needle_h]
self.rectangles.append(self.rect)
self.rectangles.append(self.rect)
self.rectangles, self.weights = cv.groupRectangles(self.rectangles, 1, 0.5)
#print(rectangles)
if len(self.rectangles):
#print('Matches found')
line_colour = (0, 0, 255)
line_type = cv.LINE_4
self.marker_colour = (255, 0, 255)
self.marker_type = cv.MARKER_CROSS
for (x, y, w, h) in rectangles:
self.top_left = (x, y)
self.bottom_right = (x + w, y + h) #finding bottom right corner to draw the rectangle
cv.rectangle(self.screenshot_img, self.top_left, self.bottom_right, self.line_colour, 1, self.line_type)
self.centre_x = x + int(w/2)
self.centre_y = y + int(h/2)
self.points = []
self.points.append((centre_x, centre_y))
cv.drawMarker(self.screenshot_img, (self.centre_x, self.centre_y), self.marker_colour, self.marker_type)
#cv.imshow('Results', self.screenshot_img)
#cv.waitKey()
else:
print('No good match found')
return self.screenshot_img
I am running it from the main and passing the method an image for 'img' and 'tree' for 'tree'. I dont even know where numpy comes into this part of the code where saying there's an error. I've tried initialising it as a string (as you can see in this code) but it made no difference. Even when I comment it out on this line I get the exact same thing on the next line; when I type in the address the problem appears on 'self.treeimage'.

weird python object attribute error

I have encountered a very weird problem.
Please see the below code. In the class there is an attribute 'weird' that is defined like all other attributes. (problem area of the code marked by
========================
========================)
But when i train to access it in one of the functions it will raise an error saying the attribute does not exist.
However if I remove the line accessing that attribute in the function, and then create an object, that attribute of the object can be accessed...
Could you please have a look at the code and see what is going wrong, i am at my wit's end here... :'(
class img_iter(DataIter):
def __init__(self, dir_train,
dir_label,
data_name = "data",
label_name = "softmax_label",
last_batch_handle = 'pad',
batch_size = 1,
#===================================================
#===================================================
color_mean = (117, 117, 117),
#===================================================
#===================================================
cut_off_size = None):
super().__init__()
# directories as attributes
self.dir_train = dir_train
self.dir_label = dir_label
# names
self.data_name = data_name
self.label_name = label_name
# read data and label files into list
self.img_data_lst = [s for s in os.listdir(dir_train) if '.jpg' in s]
self.img_data_iter = iter(self.img_data_lst)
if self.dir_label is not None:
self.img_label_lst = [s for s in os.listdir(dir_label) if '.gif' in s]
# number of data files
self.num_data = len(self.img_data_lst)
# read data when initialising
self.data, self.label = self._read()
# size limiter
self.cut_off_size = cut_off_size
# batch size
self.batch_size = batch_size
# data cursor
self.cursor = -batch_size
#===================================================
#===================================================
self.weird = np.array(color_mean)
#===================================================
#===================================================
self.last_batch_handle = last_batch_handle
def _read(self):
"""get two list, each list contains two elements: name and nd.array
value"""
data = {}
label = {}
data[self.data_name], label[self.label_name] = self._read_img()
return list(data.items()), list(label.items())
def _read_img(self):
# get next data file from the file name iterator
img_name = self.img_data_iter.__next__()
# open image file
img = Image.open(os.path.join(self.dir_train, img_name))
# find corresponding label image and open [s for s in self.img_label_lst if img_name in s][0]
label_name = img_name.split('.')[0] + '_mask.gif'
label = Image.open(os.path.join(self.dir_label, label_name))
# check image file size match
assert img.size == label.size
# convert into numpy array and manipulate, resulting 3d array: height, width, color
img = np.array(img, dtype = np.float32)
#===================================================
#===================================================
#img = img - self.weird.reshape(1,1,3)
test = self.weird
#===================================================
#===================================================
img = np.swapaxes(img, 0, 2)
# (c, h, w)
img = np.swapaxes(img, 1, 2)
# (1, c, h, w)
img = np.expand_dims(img, axis=0)
# resulting 2d array: height, width
label = np.array(label)
# (h, w)
label = np.array(label)
# (1, h, w)
label = np.expand_dims(label, axis=0)
return (img, label)
def reset(self):
self.cursor = -1
self.img_data_iter = iter(self.img_data_lst)
def iter_next(self):
self.cursor += 1
if (self.cursor < self.num_data - 1):
return True
else:
return False
def next(self):
if self.iter_next():
'''
try:
self.data, self.label = self._read()
return {self.data_name : self.data[0][1],
self.label_name : self.label[0][1]}
except:
raise
'''
self.data, self.label = self._read()
return DataBatch(data = self.data, label = self.label, \
pad=self.getpad(), index=None)
else:
raise StopIteration
#property
def provide_data(self):
"""The name and shape of data provided by this iterator"""
return [(k, tuple([1] + list(v.shape[1:]))) for k, v in self.data]
#property
def provide_label(self):
"""The name and shape of label provided by this iterator"""
return [(k, tuple([1] + list(v.shape[1:]))) for k, v in self.label]
def get_batch_size(self):
return 1
screenshots:
with call to the class attribute in the function.
remove call to the class attribute, create an object and access the same attribte directly.
You are trying to access self.weird before it is defined.
self.data, self.label = self._read()
# self._read() calls self. _read_img()
# which tries to access self.weird
# => AttributeError...
#...
# move this line above `self.data...`,
# and all should be well!
self.weird = np.array(color_mean)
Hope this helps!

Python Key Error filtering MySQL

So I have a little program which makes a DB call and then converts it into a PDF.
I have most of them working but this last one is returning a Key Error on me and I cannot figure out why.
Here is an example of the data being returned by the DB:
((None, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 26, 0, 26), (1, 1, 0, 0, 0, 17, 0, 18), (2, 0, 0, 0, 0, 15, 0, 16))
The Traceback:
Traceback (most recent call last):
File "C:\Users\Ace\AppData\Local\Programs\Python\Python36\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:/Users/Ace/Desktop/IPNV/KP_App/FML/firstapp.py", line 232, in hrday_in
hourday_filter(noodle, dest, drange)
File "C:\Users\Ace\Desktop\IPNV\KP_App\FML\dataIN.py", line 187, in hourday_filter
doc.export(pths, drange)
File "C:\Users\Ace\Desktop\IPNV\KP_App\FML\calazan.py", line 58, in export
reverse=reverse_order)
KeyError: 'h'
Im not even sure where the 'h' comes from.
Here is the function that I run the data through to prepare for the pdf generation:
def hourday_filter(tuna, pth, drange):
data = []
for hr, number, local, chicken, alligator, ace, lola, chunk in tuna:
data.append({'hour': hr,
'number': number,
'local': local,
'long': chicken,
'inter': alligator,
'income': ace,
'tandem': lola,
'total': chunk})
fields = (
('hour', 'Hour of Day'),
('number', 'Internal Calls '),
('local', 'Local Calls'),
('long', 'Long Distance Calls'),
('inter', 'International Calls '),
('income', 'Incoming Calls'),
('tandem', 'Tandem Calls'),
('total', 'Total Calls'),
)
pths = pth + '/HourofDay.pdf'
doc = DataToPdf(fields, data, sort_by='hr',
title='Hour of Day Report')
doc.export(pths, drange)
And From there the data is passed to this function to actually convert it too pdf.
class DataToPdf:
"""
Export a list of dictionaries to a table in a PDF file.
"""
def __init__(self, fields, data, sort_by=None, title=None):
"""
Arguments:
fields - A tuple of tuples ((fieldname/key, display_name))
specifying the fieldname/key and corresponding display
name for the table header.
data - The data to insert to the table formatted as a list of
dictionaries.
sort_by - A tuple (sort_key, sort_order) specifying which field
to sort by and the sort order ('ASC', 'DESC').
title - The title to display at the beginning of the document.
"""
self.fields = fields
self.data = data
self.title = title
self.sort_by = sort_by
def export(self, filename, drange, data_align='LEFT', table_halign='LEFT'):
doc = SimpleDocTemplate(filename, pagesize=letter)
styles = getSampleStyleSheet()
styleH = styles['Heading1']
styleD = styles['Heading4']
date = time.strftime("%m/%d/%Y")
date2 = 'Ran on: ' + date
date3 = ' For the period ' + str(drange[0]) + ' to ' + str(drange[1]) # Edit here to display report date range
story = []
if self.title:
story.append(Paragraph(self.title, styleH))
story.append(Spacer(1, 0.25 * inch))
story.append(Paragraph(date2, styleD))
story.append(Spacer(1, 0.015 * inch))
story.append(Paragraph(date3, styleD))
if self.sort_by:
reverse_order = False
if str(self.sort_by[1]).upper() == 'DESC':
reverse_order = False
self.data = sorted(self.data,
key=itemgetter(self.sort_by[0]),
reverse=reverse_order)
converted_data = self.__convert_data()
table = Table(converted_data, hAlign=table_halign)
table.setStyle(TableStyle([
('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'),
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
('ALIGN', (0, 0), (0, -1), data_align),
('INNERGRID', (0, 0), (-1, -1), 0.50, colors.black),
('BOX', (0, 0), (-1, -1), 0.25, colors.black),
]))
data_len = len(converted_data)
for each in range(data_len):
if each % 2 == 0:
bg_color = colors.whitesmoke
else:
bg_color = colors.lightgrey
table.setStyle(TableStyle([('BACKGROUND', (0, each), (-1, each), bg_color)]))
story.append(table)
doc.build(story)
def __convert_data(self):
"""
Convert the list of dictionaries to a list of list to create
the PDF table.
"""
# Create 2 separate lists in the same order: one for the
# list of keys and the other for the names to display in the
# table header.
keys, names = zip(*[[k, n] for k, n in self.fields])
new_data = [names]
for d in self.data:
new_data.append([d[k] for k in keys])
return new_data
Is it possible that first result of the db (the null one) is causing this? I've made about a dozen of these reports now with no problems, not sure where I am messing up here.
So thanks to FamousJameous I realized that it was indeed the first field killing my filter. The sort_by call did not know how to deal with the NULL value. I managed to fix it by removing that first field from the tuple.
The database returned the results into the variable result
From there:
new_result = result[1:]
This line removed the NULL line and stopped the error

Categories