I am trying to write data from Revit to Excel with RevitPythonShell.
So far I have collected all data in a zipped list and made an enumerated for loop to write the data to the corresponding rows and columns as following:
for index, data in enumerate(wall_zipped_list):
for count, parameters in enumerate(data):
wall_cell = worksheet_wanden.Range[(str(column_list[count]))+str(index+5)]
wall_cell.Value2 = data[count]
This is incredibly slow because the loop is calling Value2 everytime. A Revit model containing about 800 walls takes 2 minutes to write to Excel. So I tried a different method using a dictionary.
for k , v in data_dict.iteritems():
#print k, v[0]
worksheet_wanden.Range["A"+str(count)].Value2 = k
worksheet_wanden.Range["B"+str(count)].Value2 = v[0]
worksheet_wanden.Range["C"+str(count)].Value2 = v[1]
worksheet_wanden.Range["D"+str(count)].Value2 = v[2]
worksheet_wanden.Range["E"+str(count)].Value2 = v[3]
worksheet_wanden.Range["F"+str(count)].Value2 = v[4]
worksheet_wanden.Range["G"+str(count)].Value2 = v[5]
worksheet_wanden.Range["H"+str(count)].Value2 = v[6]
worksheet_wanden.Range["I"+str(count)].Value2 = v[7]
worksheet_wanden.Range["J"+str(count)].Value2 = v[8]
worksheet_wanden.Range["K"+str(count)].Value2 = v[9]
count += 1
This method is already a lot quicker. This takes about 20 seconds to fill about 800 rows with 10 columns in Excel. Am I missing some IronPython functionality which you can write dictionary or lists to Excel rows or columns?
I also looked at installing 3d party modules. But this is not really an option since RevitPythonShell usising IronPython 2.7.3 and I can't get pip install to work.
Thanks in advance.
Is it maybe faster to write to csv first in IronPython and then import it some way into excel?
This is more of a question on .NET/Excel interop. I think, based on this SO question you should be able to assign an array to a range.
That is, your current range is just one cell. You could try creating a 2d System.Array and assign it to the range... I tried it out here:
```
import clr
clr.AddReference("Microsoft.Office.Interop.Excel")
import Microsoft.Office.Interop.Excel as Excel
excel = Excel.ApplicationClass()
excel.Visible = True # makes the Excel application visible to the user
workbook = excel.Workbooks.Add()
worksheet = workbook.Worksheets.Add()
from System import Array
xlrange = worksheet.Range["A1:c3"]
a = Array.CreateInstance(object, 3, 3)
i = 0
for row in range(3):
for column in range(3):
a[row, column] = i
i += 1
xlrange.Value2 = a
```
This produces a result like this:
More information on IronPython and Excel can be found here: http://www.ironpython.info/index.php?title=Interacting_with_Excel
You could try installing the xlwt module and use that - avoiding COM interop.
It works
i = 0
xlrange_revit_type = worksheet_data.Range["C2:C" + str(len(revit_type_list)+1)]
a = Array.CreateInstance(object,len(revit_type_list), 3)
while i < len(revit_type_list):
a[i,0] = revit_type_list[i]
i += 1
xlrange_revit_type.Value2 = a
Is it possible to install a 3d party module like xlwt for RevitPythonShell? I can't find any documentation.
If you're referring to the Cells notation that you can use in VB, I don't know why it does not work, but you could create a definition:
def Cells(a,b):
return str(chr(a+96) + str(b))
Now you could call something like:
x1range = ws.Range(Cells(1,1),Cells(5,10))
and it will work the same. That is what I do.
Related
Just recently started using Python, the version I have is 3.5
I'm using openpyxl to write a list to a single column on an excel sheet, nothing too complicated, here is the code:
import openpyxl
import random
wb = openpyxl.load_workbook('testSave.xlsx')
target_sheet = wb.get_sheet_by_name('Destination')
##create a list with random numbers
for i in range(1,20):
container.append(random.randint(1,20))
for j in container:
rowIn = container.index(i)
target_sheet.cell(row = rowIn + 1, column = 1).value = container[rowIn]
wb.save('testSave.xlsx')
When I open the workbook several of the list items are missing, 10 in total, not sure what I'm doing wrong, been researching about this for a few days now without any luck, it is probably something silly, any help will be greatly appreciated.
list.index() is not doing what you think it does - it returns the first index of the element value found in the list. Given that you can have duplicate elements in the list you will never get indexes of the repeated elements. If you want to enumerate your list, use enumerate():
import openpyxl
import random
wb = openpyxl.load_workbook('testSave.xlsx')
target_sheet = wb.get_sheet_by_name('Destination')
##create a list with random numbers
for i in range(1,20):
container.append(random.randint(1,20))
for i, j in enumerate(container):
target_sheet.cell(row = i + 1, column = 1).value = j
wb.save('testSave.xlsx')
I am trying to write a list of values to an Excel spreadsheet, starting at a specific cell. The values will be written periodically and the new values will replace the existing values, so writing will always start in cell F2. I have tried multiple versions that I found on SO and other sites but I keep getting various errors, most recently a KeyError = 0 for these efforts :
for rowNum in range(len(list)):
ws.cell(row=rowNum+1, column=5).value = list[rowNum]
for i in range(len(list)):
ws['F' + r].value = list[i+1]
PLEASE help ! Many thanks in advance.
Edit - I found the solution in "Automate the Boring Stuff with Python", chapter 12. I converted my dataframe to a dictionary and then this worked :
for rowNum in range(2, ws.max_row):
item = ws.cell(row=rowNum, column=1).value
if item in new_dict:
ws.cell(row=rowNum, column=5).value = new_dict[item]
I just tried the script below and it worked fine for me.
from openpyxl import Workbook
wb = Workbook()
# grab the active worksheet
ws = wb.active
# Data can be assigned directly to cells
ws['A1'] = 42
# Rows can also be appended
ws.append([1, 2, 3])
# Python types will automatically be converted
import datetime
ws['A2'] = datetime.datetime.now()
# Save the file
wb.save("C:\\Users\\your_path_here\\Desktop\\sample.xlsx")
I am trying to read data from my Excel spreadsheet and so far i have been able to do it using the code below but i cant run iterations.
from openpyxl import load_workbook
import numpy as np
wb = load_workbook('c:\ExcelData\pyExcel.xlsx')
ws = wb.get_sheet_by_name('Sheet1')
table = np.array([[cell.value for cell in col] for col in ws['A2':'A3']])
print(table)
Another Example:
val1=2
val2=1
wb = load_workbook(os.path.abspath(os.path.join(os.path.dirname(__file__),'c:\ExcelData\pyExcel.xlsx')))
sheet = wb.get_sheet_by_name('Sheet1')
c = sheet.cell(row=val1, column=val2).value
d = sheet.cell(row=val2, column=val2).value
print(c)
print(d)
So far what this does is to read a harcoded row and cell from an excel file and print or assign the value to a variable, But I am looking for a way to run iterations of data.. I want to use it as a data table when the first rows of all the columns will be executed the first time and then at the end the script will start over again but using the next row.
Thanks.
pinky you should use variables into the table = np.array([[cell.value for cell in col] for col in ws['A2':'A3']])
example ws['variable':'variable']]) or ws['ANUMBERVARIABLE':'ANUMBERVARIABLE']])
#Pinky Read this page http://openpyxl.readthedocs.org/en/latest/tutorial.html and try to find your answer. If you still did not understand from it, I'll try to help you with a code. I feel this is the best way you could actually learn what you are doing rather than just receiving the code directly.
I am using xlwings and am trying to sum two cells, A1 + B1, and have the output entered into a third cell C1. I want to to do this for a range (A1->A9) + (B1->B9) and have them written to cells (C1->C9). My current command is Range('C3').value = [sum(x) for x in zip(Range('A3:A9').value, Range('B3:B9').value)] This sums the values correctly but the answers are written out horizontally to cells C3-I3. I know that the command Range('A1').value = [[1],[2],[3],[4],[5]] would list the elements of a list vertically but I am not sure how to incorporate this into my command.
Any help would be appreciated
Making this easier is an open issue. For simple lists, you can do the following (note that on Python 2, you don't need list around zip:
Range('C3').value = list(zip([sum(x) for x in zip(Range('A3:A9').value,
Range('B3:B9').value)]))
If you have numpy installed, the same can be achieved like that:
import numpy as np
Range('C3').value = (Range('A3:A9', asarray=True).value +
Range('B3:B9', asarray=True).value)[:,np.newaxis]
Try this code:
import xlwings as xw
sht = xw.Book().sheets[0]
sht.range('C3').options(transpose=True).value \
=[sum(x) for x in zip(sht.range('A3:A9').value, sht.range('B3:B9').value)]
To make values print out in Excel vertically you simply need to covert them in lists, to get list of lists finally, just as you described.
from xlwings import Workbook, Range
wb = Workbook('example.xlsx')
a_col = Range('A1').vertical.value # or Range('A1:A9').value if you wish
b_col = Range('B1').vertical.value
c_col = zip(a_col, b_col)
c_col = [[sum(x)] for x in c_col] # use '[]' here inside of list constructor
Range('C1').value = c_col
wb.close()
I am stuck trying to export matlab uitable data to excel. I tried many things, and It has been impossible to solve this problem. After many days, I tried the code below using windows and it does work perfect, however, using the same for Macintosh is not longer working. The output is as follows:
"Error using dlmwrite (line 118) The input cell array cannot be converted to a matrix"
Searching for more information, I found an answer here ,(Using "xlswrite" MATLABs for cell arrays containing strings of different size) which doesn't work perfect. Finally I found this method which applies only for matlab using windows (http://www.mathworks.es/matlabcentral/answers/20819-export-uitable-s-data-to-a-spreadsheet-excel).
I hope you can help me with this problem.
Thanks in advance
Hector
function Save_File
hf = figure;
hExportButton = uicontrol('Parent',hf,'Units',...
'normalized','Position',[0 0.81 0.22 0.18],'Style','Pushbutton',....
'String',' Export Data!','FontSize',20,'Callback',#ExportButton_Callback);
dat = rand(5,5);
t=uitable('Data',dat,'ColumnName',{'First','Second','Third','Fourth','Fifth'},...
'Position',[7 10 500 300]);
Data=get(t,'Data');
ColumnName=get(t,'ColumnName');
set(t,'ColumnWidth',{93.5})
function ExportButton_Callback(~,~)
NewData= num2cell(Data,ones(size(Data,1),1),ones(size(Data,2),1));
CombData=[ColumnName';NewData];
FileName = uiputfile('*.xls','Save as');
xlswrite(FileName,CombData);
end
end
You should be able to convert the cell array into a number array with a cell2mat command and then use csvwrite or dlmwrite.
If the combo of numbers and strings is the issue, as stated in my comment above, you can use some simple looping to do this all for you. I posted some sample code below.
% Creating some temporary data for proof of concept
mat = randi([1,5],10,2);
header = {'Col1','Col2'};
cellVals = [header;num2cell(mat)];
% the real code that does the writing
fh = fopen('temp.csv','w'); % open a file with write privileges, will overwrite old versions
for ii = 1:size(cellVals,1)
first = 1;
for jj = 1:size(cellVals,2)
if first
fwrite(fh,num2str(cellVals{ii,jj},'%f'));
first = 0;
else
fwrite(fh,[',',num2str(cellVals{ii,jj},'%f')]);
end
end
fwrite(fh,sprintf('\r\n')); % print line break
end
fclose(fh); % close file out when done writing