I'm having trouble creating a fiddly html table in python 3.4. The templater is html 1.16. Here's a simplified version of the problem: I would like to traverse a list. For each list item, I would like to write the data to a html table. The table should be two columns wide.
from html import HTML
#create html object
h = HTML()
comments=["blah1",
"blah2",
"blah3"
]
#create table object
c_table = h.table.tbody
for i, comment in enumerate(comments):
#create row if we are at an odd index
if i % 2 != 0:
row = c_table.tr
row.td(comment)
else:
#it is intended to add another <td> to the current row here
#but because the row was declared in the if block, it is out of scope
row.td(comment)
#write the html output now
print(h)
The difficulty is with the templater, specifically: accessing the row object for the second cell of the row without causing the </tr> closing tag. I have to create new cells through the row object, otherwise if I call c_table.tr.td it closes the row with </tr> and starts a new one.
Can anyone clever think of any code trickery that achieves what I'm trying to do in these circumstances?
Your comment is simply incorrect. Python does not have block scope, and the row that is defined in the if block is accessible in the else.
In fact, you can take the td out of the if block, and remove the else altogether.
You can't access that row object, because it was created inside the first if. In order to access it in your "else", you'll have to create it outside both clauses, which doesn't help you achieve your goal.
Try dividing the list into "chunks" - a list of lists with 2 objects each.
h = HTML()
comments=["blah1",
"blah2",
"blah3",
"blah4",
"blah5"
]
fixed_list = []
for i in xrange(0, len(comments), 2):
fixed_list.append(comments[i:i+2])
Now fixed list looks like this -
[["blah1", "blah2"], ["blah3", "blah4"], .....]
And now you can easily iterate over that list, and create a row for each list -
#create table object
body = h.body
tb = body.table
for comments_list in fixed_list:
row = tb.tr
for comment in comments_list:
row.td(comment)
print h
Related
Let me start with the background: I have a Dataframe. It's a column of hyperlinks. I use a forLoop to extract the hyperlinks with an attribute target and add them to an appended column.
Result of successful forLoop.
now let me throw curveball: a blank/gap. let's say that there is a gap in the column and Source C is out of the picture – what happens to the forLoop then?
Result of unwanted forLoop
what if instead of deleting the entire row, I want the forLoop to put a blank cell there? so that no data is being rearranged and Source C has a blank cell or NaN cell next to it. Does that make sense? What are my options? (also note that my print() function is not really working as I intend it to.) for what it's worth, ws.cell is an openpyxl operation that accesses a cell of an Excel sheet.
Here is the hard code just in case:
links = []
for i in range(2, ws.max_row + 1): # 2nd arg in range() not inclusive, so add 1
try:
links.append(ws.cell(row=i, column=1).hyperlink.target)
except AttributeError or NaN:
print('nothing here')
df['link'] = pd.Series(links)
df
Can't see your input data, i.e. the input xlsx file and may not be able make a sure solution. Anyway, have you tried the following?
...
except AttributeError or NaN:
lists.append('') # still append a blank string to the list
print('nothing here')
I have been trying to figure out how to add cell 0 from all tables in a word document to my_list , I managed to add from a specific table placement number (96) but can't seem to pull all tables data, I used this for table array number 96 and it worked
`tables = list(d.tables)
tbl = d.tables[96]
my_list = []
for rw in tbl.rows:
my_list.append(rw.cells[0].text)
print(my_list)
tried a lot of different options to iterate all tables and add to my_list, one being below but it gives the error
'Table' object has no attribute 'cells'
my_list = []
tbl = list(d.tables)
for val in tbl:
for rw in tbl:
my_list.append(rw.cells[0].text)
print(my_list)
any help is greatly appriciated
This is not a complete runnable example so I cannot verify it, but:
This part is Bad Python:
for val in tbl:
for rw in tbl:
You are iterating over tbl twice, and all the outer loop is doing is running the inner loop len(tbl) times. The second line might be
for rw in val:
but I am not 100% on that due to Not Enough Information.
(Also, consider renaming both tbl and val to something resembling what they contain: list_of_tables and a_table would be far better. Also, use row instead of rw, as Python does not have some unreasonable variable name length width.)
Problem Statement
I'm trying to select rows of data from my QtableWidget and print them out to my console just so I can test some things, with the end goal being able to plot the data. However I can never grab the whole row of data.
Background
I have made a GUI that can embed several QTableWidgets by importing a specifically formatted CSV file. The goal is to be able to pull data from multiple rows from the same or different tables and then plot them in a side by side fashion. Where each row of data will be its own dataset and have its own plot, but there will be multiple plots on the same figure.
To complete this task I have made a window called CompareWindow that opens when a Qpushbutton called "Compare" is pressed. The window prompts the user to type in the names of the tables and the respective rows from that table they wish to plot.
After this information is submitted I have dictionary that I can reference which has saved all the QTableObjects that have been instantiated. Where the keys are the names given to the tables which are connected to their corresponding Table Object.
Problem
The two main methods I have tried to grab the row data are…
The first idea was using TableObject.selectRow() command I would iterate through the rows I wanted, but whenever I did this to it would return a nonetype.
The second method I tried was to iterate a given rows columns so it would fill a list one by one by appending the item values. However when I did this it only filled the list with the same number repeatedly, which was the first cell in my Qtable.
Even when I explicitly called a certain row or column I would get the same output. The output being pulled is .12, the number from the first cell in my CSV file.
Here is the code in question I'm having problems with.
def initiateMultiPlot(self, tableV, rowV, PlotV):
"""
1. Match TableName values with the key values in our TableDB
2. When we find a match look at that key's corresponding Table Object, and iterate
through that objects rows and select the rows specified by rowV
3.Call plot for those values
"""
#calls my class and creates a blank figure where eventually we will plot data on
f = CreateFigure.FigureAssembly()
print("")
for i in tableV:
"""
tableV: is list of strings that represent assigned tablenames [Table1, Table2, Table3]
rowV: is a list, containing lists representing rows from corresponding Tables the user wishes to plot.
for example [[1,2],[3,4],[1]] means rows 1,2 from table1, rows 3,4 from table2... so on
PlotV: is a string that is ethier "box" or "whisker" to tell what method to plot. Default right now
is to do a simple boxplot
"""
print("Creating table instance")
#Table Dictionary is setup so the names of the Tables (tableV) are the keys of the dictionary
#and the actual table objects are referenced by these keys
self.TableOBJ = self.TableDictionary[i]
print("Data Type for the table object is..................{}".format(type(self.TableOBJ)))
#empty list that will store our row data
self.Elements = []
try:
for rows in rowV:
for i in rows:
print("rowV value is... {}".format(rowV))
print("current row list{}".format(rows))
print("i value is {}".format(i))
print("itterating")
for j in range(self.TableOBJ.columnCount()):
print("i value is ...{}".format(i))
print("j value is .... {}".format(j))
#FIRST idea try selecting entire row of data
print("i value is ...{}".format(i))
print("j value is .... {}".format(j))
#entire row returns none-type
EntireRow = self.TableOBJ.selectRow(i)
print(EntireRow)
#selecteditems
#SECOND idea try using for loop and iterating through every value in a row
item = self.TableOBJ.itemAt(i,j)
#explicit call for (row 1, col 1) and (row 3, col 3), both which output .12
print(self.TableOBJ.itemAt(1,1).text())
print(self.TableOBJ.itemAt(3,3).text())
print("printing item...... {}".format(item))
element = item.text()
print(element)
#list of .12
self.Elements.append(element)
#elements = [self.TableOBJ.item(i, j).text() for j in range(self.TableOBJ.columnCount()) if
# self.TableOBJ.item(i, j).text() != ""]
#print(elements)
except Exception as e:
print(e)
print(self.Elements)
Here is my GitHub link containing all my files: https://github.com/Silvuurleaf/Data-Visualize-Project
The problem occurs in my file Perspective.py in the method initiateMultiPlot. The file CompareWindow.py sends a signal to my Perspective.py and is connected to initateMultiPlot. Please inquire if anything requires more in depth explanation.
According to the documentation:
QTableWidgetItem *QTableWidget::itemAt(int ax, int ay) const
Returns the item at the position equivalent to QPoint(ax, ay) in the
table widget's coordinate system, or returns 0 if the specified point
is not covered by an item in the table widget.
That is, returns the given item x and y which are graphical coordinates with respect to QTableWidget, and clearly is not what you are looking for.
You must use the item():
QTableWidgetItem *QTableWidget::item(int row, int column) const
Returns the item for the given row and column if one has been set;
otherwise returns 0.
But in your case will not work unless you do the following change:
class CreateTable(QTableWidget):
....
for j in range(0, m):
self.item = QTableWidgetItem(str(round(ValList[j], 6)))
# print("{}, {}".format(i, j))
self.setItem(i, j, self.item)
to:
class CreateTable(QTableWidget):
....
for j in range(0, m):
item = QTableWidgetItem(str(round(ValList[j], 6)))
# print("{}, {}".format(i, j))
self.setItem(i, j, item)
That is, you change your self.item to item.
The problem is that at first glance the error is rather difficult, the QTableWidget class has an item() function, but when you use the self.item statement you are replacing that call, ie when python reads that statement it will use the attribute and not the function , So you get the error:
TypeError 'xxx' object is not callable
i have a query which returns me a Viewobject with all the entries i want to process. I know i can iterate over this view Object so that i can use the single entries for my purposes.
Now i want to extract only the first and the last row. The first row is no problem because i can just iterate and break the loop after the first item.
Now my question is, how to get the last element from the View.
I tried by:
for row in result_rows:
rowvalue = row[3].value
diagdata = rowvalue[models.DIAGDATA]
if models.ODOMETER in diagdata:
start_mileage = diagdata[models.ODOMETER]
start_mileage_found = True
break
row = result_rows[len(result_rows)]
rowvalue = row[3].value
diagdata = rowvalue[models.DIAGDATA]
if models.ODOMETER in diagdata:
end_mileage = diagdata[models.ODOMETER]
end_mileage_found = True
The second value i obviously wont get, because view has neither a length nor can i access the rows by a index. Has anyone an idea how to get the last element?
You might run another request but with descending=True option, so that the server will stream results in reverse order.
Or you can convert iterator to array which basically the same a iterate through all values. I'm not a python expert, but it seems like list(result_rows) will do it for you. And when you are doing len(...) it probably doing it for you implicitly. There is rows_returned method to get the number of rows without turning it to list.
I am looping through table rows in a table, but the first 1 or 2 rows doesn't have the elements I am looking for (they are for table column headers etc.).
So after say the 3rd table row, there are elements in the table cells (td) that have what I am looking for.
e.g.
td[0].a.img['src']
But calling this fails since the first few rows don't have this.
How can I guard against these cases so my script doesn't fail?
I get errors like:
nonetype object is unsubscriptable
Simplest and clearest, if you want your code "in line":
theimage = td[0].a.img
if theimage is not None:
use(theimage['src'])
Or, preferably, wrap the None check in a tiny function of your own, e.g.:
def getsrc(image):
return None if image is None else image['src']
and use getsrc(td[0].a.img).
Starting from tr:
for td in tr.findChildren('td'):
img = td.findChild('img')
if img:
src = img.get('src', '') # return a blank string if there's no src attribute
if src:
# do something with src