Openpyxl Keeping formulas but copying values - python-3.x

My workbook has 6 sheets. The last 3 sheets are a bunch of formulas that I currently manually copy and paste values into the first 3 sheets. I am using wb.copy_worksheet() to make the copies and loading the work book as data_only = True. However, when I save, the formulas are all gone due to loading it as data_only. Is there a way I can copy the values but keep the formulas? The sheets are too large to go cell by cell.
Heres my code:
import openpyxl
wb = openpyxl.load_workbook("symbols.xlsx", data_only=True)
ws = wb.get_sheet_names()
print (ws)
Value = ws[0:3] #set equal to first 3 sheets
BB = ws[3:7] #set equal to last 3 sheets
for s in range(0, len(Value)):
CopyBB = wb.copy_worksheet(wb[BB[s]]) #copy from bb sheet
CopyBB.title = Value[s]
myorder = [6, 7, 8, 3, 4, 5, 0, 1, 2] #this is to reorder the sheets that got copied.
wb._sheets =[wb._sheets[i] for i in myorder]
wb.remove_sheet(wb.worksheets[8])
wb.remove_sheet(wb.worksheets[7])
wb.remove_sheet(wb.worksheets[6])
wb.worksheets[0].title = "Securities Values"
wb.worksheets[1].title = "Indices Values"
wb.worksheets[2].title = "Currencies Values"
return wb.save("symbols.xlsx")

I had a similar issue. You have to use ='MVSM!A1', where MVSM is the sheetname then A1 is the cell value. Just use that when assigning cell value whilst using openpyxl.

Related

Python: Issue reading and writing with formulas from one excel sheet to another. Using openpyxl

I am new to programming and have a question with python, openpyxl, and formulas. At the moment, I am trying to use a formula to sum multiple cells on one excel sheet (xlsx), read it, and write it to another excel sheet. This is my current code:
# Give the location of the Departments Report
path4 = "Departments - June 29, 2021 to June 29, 2021.xlsx"
# To open the workbook
# workbook object is created
wb4 = openpyxl.load_workbook(path4)
# Get workbook active sheet object
# from the active attribute
ws5 = wb4.active
# Cell object is created by using
# sheet object's wb[] method.
ws5['I100'] = "=SUM(I8:I99)"
Dc1 = ws5['I100']
# Give the location of the write file
path2 = "Daily Financials.xlsx"
# To open the workbook
# workbook object is created
wb2 = openpyxl.load_workbook(path2)
# Get desired workbook sheet
ws6 = wb2["COS"]
# Cell is specified with value
ws6["CK7"].value = Dc1.value
# Finally, save and close the Excel file
# via the save() and close() method.
wb2.save('Daily Financials.xlsx')
wb2.close()
There are no errors when running the code, however, the formula is written on the new excel sheet as "=SUM(I8:I99)" and not the value of those from the first excel sheet. I have looked around and tried adding ".value", but I am struggling to figure this out.
Current excel output
Thanks for any help.
Since you are already using python, I suggest a loop that will put the actual data (not formula) into the cell in ws5:
# Cell object is created by using
# sheet object's wb[] method.
counter = 0
for c in ws5['I8:I99']:
counter += c[0].value
ws5['I100'] = counter
#or with list comprehension: ws5['I100'] = sum([c[0].value for c in ws5['I8:I99']])
Dc1 = ws5['I100']

Trying to add new worksheets in vba

I am trying to add 5 new worksheets in my vba code. Originally my code only required 1 sheet and now 6 sheets need to be present. Each have a unique name. I will have different lines of code throughout the code that need to be added to each worksheet.
Sheets(1).Name = "Make-Ready"
Worksheets.Add(After:=Sheets(1)).Name = "My New Worksheet"
Set MRBook = Worksheets("Make-Ready").Parent
There is a portion of the code that errors out when my variable MRBook is defined.
If (RDBook.Sheets("RawData").Cells(PoleRow - 12, "BZ").Value) = "No" Then MRBook.Sheets("Make-Ready").Range(Cells(PoleRow, 87), Cells(PoleRow, 88)).Style = "Bad"
The part that errors out is the MRBook.Sheets("Make-Ready"). Do you know which part of these two examples could be the issue?
I believe you are not qualifying Cells properly. By that I mean that in the Then line, the Cells keyword is not referring to the proper worksheet.
Cells (unqualified) references the active worksheet. So your program should work if Make-Ready happens to be the active worksheet.
In the code below, because of the With.. and the leading dot, Cells will reference Make-Ready no matter what worksheet is active.
Try:
With MRBook.Sheets("Make-Ready")
If (RDBook.Sheets("RawData").Cells(PoleRow - 12, "A").Value) = "No" Then .Range(.Cells(PoleRow, 87), .Cells(PoleRow, 88)).Style = "Bad"
End With
As pointed out by #EEM,
If (RDBook.Sheets("RawData").Cells(PoleRow - 12, "A").Value) = "No" Then Range(.Cells(PoleRow, 87), .Cells(PoleRow, 88)).Style = "Bad"
(no dot preceding Range) would also work since both arguments are qualified by the worksheet.

Using xlrd to iterate through worksheets and workbooks

I am a total noob. I need to grab the same cell value from every other sheet (starting at the third) in a workbook and place them into another. I continue to get an IndexError: list index out of range. There are 20 sheets in the workbook. I have imported xlrd and xlwt.
Code:
sheet_id = 3
output = 0
cellval = enso.sheet_by_index(sheet_id).cell(20,2).value
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
book_cp.save(path)
for sheet_id in range(0,20):
sheet_enso = enso_cp.get_sheet(sheet)
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
sheet_id = sheet_id + 2
output = output + 1
Your problem most probably exists in here:
sheet_id = 3
cellval = enso.sheet_by_index(sheet_id).cell(20,2).value # row:20, column:0
Check the following:
1- Make sure that sheet_id=3 is what you want (where the index of sheets starts from 0), so the 3rd sheet has index=2 unless you want the 4th sheet.
2- Check cell(20,0) exists in the selected sheet (where cell(0,0) is the first cell).
Plus, you don't need to define sheet_id
instead change the range to (2: 3rd sheet, 21: for 20 sheets) > in range(2,21) where:
range([start], stop[, step])
start: Starting number of the sequence.
stop: Generate numbers up to, but not including this number.
step: Difference between each number in the sequence.
Reference: Python's range() Parameters
and to get cellval from every sheet, put cellval inside the loop.
The final code could be:
output = 0
for sheet_id in range(2,21): # (starting at the 3rd sheet (index=2), stopping at 20 "21 not included")
cellval = enso.sheet_by_index(sheet_id).cell(20,0).value # row 20, column 0
#sheet_enso = enso_cp.get_sheet(sheet) # i don't know if you need that for something else
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
output = output + 1
book_cp.save(path)
again check cell(20,0) exists in all source sheets to avoid errors.

Matlab number of rows in excel file

is there a command of Matlab to get the number of the written rows in excel file?
firstly, I fill the first row. and then I want to add another rows in the excel file.
so this is my excel file:
I tried:
e = actxserver ('Excel.Application');
filename = fullfile(pwd,'example2.xlsx');
ewb = e.Workbooks.Open(filename);
esh = ewb.ActiveSheet;
sheetObj = e.Worksheets.get('Item', 'Sheet1');
num_rows = sheetObj.Range('A1').End('xlDown').Row
But num_rows = 1048576, instead of 1.
please help, thank you!
If the file is empty, or contains data in only one row, then .End('xlDown').Row; will move to the very bottom of the sheet (1048576 is the number of rows in a Excel 2007+ sheet).
Test if cell A2 is empty first, and return 0 if it is.
Or use Up from the bottom of the sheet
num_rows = sheetObj.Cells(sheetObj.Rows.Count, 1).End('xlUp').Row
Note: I'm not sure of the Matlab syntax, so this may need some adjusting
You can use MATLAB's xlsread function to read in the spreadsheet. This obtains the following fields:
[numbers strings misc] = xlsread('myfile.xlsx');
if you do a size check on strings or misc, this should give you the following:
[rows columns] = size(strings);
testing this, I got rows = 1, columns = 10 (assuming nothing else was beyond 'A' in the spreadsheet).

Convert text to number in Excel in VBA [duplicate]

This question already has answers here:
VBA: Convert Text to Number
(11 answers)
Closed 4 years ago.
For some reason Excel is converting my number into text and adding a preceding apostrophe in every cell in column E3 and F3.
I need to convert columns E3:F3 back to numbers and format them to currency. How do I do that?
A1:K2 is the header.
The code below is not working:
Set wb = objApp.Workbooks.Open("aFile.xls", True, False)
wb.Sheets(1).Rows(2).Delete
wb.Sheets(1).Range("E3:F3") = Mid(wb.Sheets(1).Range("E3:F3"), 2,
Len(wb.Sheets(1).Range("E3:F3")) - 2)
wb.Sheets(1).Range("E3:F3").NumberFormat = "$#,##0.00"
If your text is only a number, the answer is simple. Multiply it by 1.
Say cell A1= '00001234 or a formula or macro returns a piece of text, multiply the answer by 1.
"00001234" * 1 = 1234.
I want to extract the value of a Label or a txtBox on a VBA form.
Num = lblText * 1
Another example:
If .txtLevel10 * 1 > 50 Then...etc.
Also works with some other data types "16-Jan-15" *1 = 16/1/15
Works in Excel & VBA but only if there are no other characters in the original text.
Cheers
Assuming you want the same currency formatting you get from the toolbar, this works:
wb.Sheets(1).Range("E3:F3").Formula = wb.Sheets(1).Range("E3:F3").Value
wb.Sheets(1).Range("E3:F3").Style = "Currency"
Just using worksheet.Range() with no properties forces Excel to guess exactly which property you actually mean (this is called the "default property"), and you get inconsistent results.
Try:
Range("E3:F3").Style = "Currency"
Try highlighting that column and doing Data->Text To Columns (Excel 2003; in 2007+ Text to columns is on one of the ribbons). Click 'Delimited', then 'Next', Next again, then select General as the format. This should convert the whole column into a number.
If this works, it is easily automated. Let me know if you need code.
EDIT - you have to do one column at a time.
Len(wb.Sheets(1).Range("E3:F3"))
For me this just (as expected) throws an error. You'll have to process each cell individually to use your approach.
Dim c as Range
Set wb = objApp.Workbooks.Open("aFile.xls", True, False)
With wb.Sheets(1)
.Rows(2).Delete
For each c in .Range("E3:F3").cells
c.Value = Mid(c.value, 2, Len(c.value)-2)
c.NumberFormat = "$#,##0.00"
next c
End With
This, actually, works. The key is to apply format before setting the value:
Set wb = objApp.Workbooks.Open("aFile.xls", True, False)
wb.Sheets(1).Rows(2).Delete
wb.Sheets(1).Range("E3:F3").NumberFormat = "$#,##0.00"
For Row = 3 To 3 'your rows range in case you need iterate through (1 row only in your case)
For Column = 5 To 6 'E3:F3
wb.Sheets(1).Cells(Row, Column) = Mid(wb.Sheets(1).Cells(Row, Column), 2, Len(wb.Sheets(1).Cells(Row, Column)) - 2)
Next Column
Next Row

Resources