Openpyxl not removing sheets completely from Excel Sheet - openpyxl

I was wondering if someone can explain why openpyxl is not removing sheet completely. I am using default openpyxl function. Thought this is deleting the sheet but the traces are still there in the developer tab. If you can help to fix this, I would be very grateful.
`remove_sheet(worksheet)`
While I am now using this alternative approach, but I beleive this is not efficient, since I first delete the sheet, then again use openpyxl to write it
xl = win32com.client.Dispatch('Excel.Application')
book = xl.Workbooks.Open(Filename = file, ReadOnly=False)
xl.Application.Run("delSheets.delSheets")
book.Save()
book.Close()
xl.Application.Quit()
del xl

Related

Openpyxl throws no errors but no changes to workbook are being made?

I've been trying to make a job finder using beautiful soup, and now want to move what I find into an excel file. But even when I try running the simplest changes to a worksheet, like in the code below, nothing actually changes and there are no errors.
I've tried copying tutorial code from online, as I assumed it's my simple mistake (which it probably is), but there is still no change.
import openpyxl
from openpyxl import Workbook
from openpyxl import load_workbook
wb = load_workbook("PracticeWorkbook.xlsx")
ws = wb.active
ws.cell(row=1, column=1,value='please work')
wb.save("PracticeWorkbook.xlsx")
Your code works for me, bearing in mind that because you're using load_workbook you need to already have 'PracticeWorkbook.xlsx' as an existing file.

Removing links from copied worksheet

What I want to do
I want a code in my workbook (wbDestination) that opens another workbook (wbBosOriginal) and copies an entire sheet as values (wbBosOriginal has a lot of code in it, in modules and in the worksheet in question, and I do not want this code because it references stuff in wbB that doesn't exist in wbDestination). I have had great problems pasting as values, because it will not paste columns and rows that are currently hidden. So this is why I decided to import the whole sheet instead.
What I tried and what's wrong with it
Here is a block of code I used to copy the worksheet in the destination workbook, in the last index position. The problem with it is that some links still exist to the old workbook (Formulas, validation lists, conditionnal formatting). I have deleted all these links but STILL when I paste the sheet successfully, save and reopen, I have an error saying some content is unreadable. I believe there are still some elements linked to the old workbook.
Set wbBosOriginal = Workbooks.Open(strChosenPath, ReadOnly:=True)
With wbBosOriginal.Sheets("BOS")
.Visible = True
'Pastes the ws in last position in wbDestination
.Copy after:=wbDestination.Sheets(wbDestination.Worksheets.Count)
Set wsNewBos = Worksheets(Worksheets.Count)
'Deletes VBA code in the copied sheet
ThisWorkbook.VBProject.VBComponents.Item(wsNewBos.CodeName).CodeModule.DeleteLines 1, _
ThisWorkbook.VBProject.VBComponents.Item(wsNewBos.CodeName).CodeModule.CountOfLines
End With
The worksheet is successfully pasted with no code in it, with everything else it had previously. I then remove all formulas, conditionnal formatting, and validation lists. Even after removing those as well, I still get an error when opening the workbook.
My question
Apart from conditional formatting, validation lists, VBA code, and formulas linking a worksheet that was pasted to a new workbook, what other elements could cause the workbook from opening in repair mode every time due to existing links to the old workbook?
If my question is not clear, comment and I will clarify.
Dealing directly with VBE seems a bit heavy-handed to me. If your code is manipulating several workbooks, I would put the code in an add-in and not have it in any workbook. (Technically *.xlam addins are workbooks, but when I say "workbook" I mean normal *.xls, *.xlsx, *.xlsm, etc.)
That said, if you're just copying cell values (which may be formulas) between different workbooks, you shouldn't have any dependencies other than cell references, named ranges, and user-defined functions in the original workbook. I would make sure there are none of those. Please also share how you are ensuring your formulas do not have broken references.
If the issue you are having is caused by trying to avoid hidden columns and rows not allowing pastevalues, why not unhide the rows and columns and then copy only the values to the new book?
Just cycle through each of the sheets in the original book and use the method .UsedRange.Hidden = False. As far as I am aware, this should unhide every cell on the sheet and allow you to do the original pastevalues calls
This works fast and smooth (it's harder to delete ALL the data Imo):
Sub tests()
Dim AllRange As Range: Set AllRange = ActiveSheet.UsedRange
Dim ItemRange As Range
Dim myWbDestination As Workbook: Set myWbDestination = ThisWorkbook
Dim SheetDestination As String: SheetDestination = ("Sheet2")
For Each ItemRange In AllRange
With myWbDestination.Sheets(SheetDestination)
.Range(ItemRange.Address) = ItemRange.Value
End With
Next ItemRange
End Sub
Repair mode can be triggered by many factors, you would need to post the code you are getting to look for an explanation, it would be like asking why vba may broke

VBA error 1004 on Paste from CSV file with CSV file opened first

I'm a beginner on Excel VBA and working on a little tool at work. We use a tool to measure our NPS-score, and therefore I can download all our comments as CSV file. I created a VBA, to paste all these comments in an worksheet and convert it to columns and do the math.
If I open my Excel file first, then download the comments, manually copy the comments and run the script, it works fine. But if I download the comments at first, then open my Excel file and run the script, it throws a 1004 error, Method Paste of class Worksheet failed.
I've tried a lot of answers on here, but none of them seems to work. This is the part of script in the beginning to paste the comments:
Application.ScreenUpdating = False
Dim wb As Workbook
Set wb = ThisWorkbook
wb.Activate
Sheets("Hulpblad").Visible = -1
Sheets("Hulpblad").Paste Destination:=Sheets("Hulpblad").Range("A1")
Application.CutCopyMode = False
I also tried to record a macro and use the Excel generated code, but all the answers give the same error.
Next to that, by some users of the script it doesn't matter in which order you open the files, it always throws the 1004 error. Can somebody please help :-)
1004 is an error, that is generated, when you try to change a protected sheet.
In your code, you are trying to paste a value, which cannot be done, because the sheet is protected.
Try to unprotect it first, before pasting the value and then protect it again.
I think there is no copy method in your statement. You are trying to paste the content directly

OpenPyXL always return None for a cell with hyperlink

(My ultimate purpose is to append clickable cells to existing XLSX.)
I use the code below to extract the cell's display value and the hyperlink.
from openpyxl import load_workbook
xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)
wsheet1= wbook.get_sheet_by_name('mysheet')
cell1 = wsheet1.cell('A1')
print cell1.value
print cell1.hyperlink
print wsheet1['A1'].value
print wsheet1['A1'].hyperlink
But it returns the following things:
URL1
None
URL1
None
Why the hyperlink always None? I did add hyperlink manually for cell A1 and the hyperlink works in Excel 2013.
Unfortunately, it's a bug.
It's a bug in 2012...
Some related thread:
Extracting Hyperlinks From Excel (.xlsx) with Python
Some details of my experiment with hyperlink. I am using OpenPyXL 2.3.3.
I can add hyperlink to cells.
from openpyxl import load_workbook
xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)
wsheet1= wbook.get_sheet_by_name('mysheet')
cell1 = wsheet1.cell('A1')
cell1.hyperlink = r'http://www.example.com'
cell1.value=r'XXX'
wbook.save(xlsFile)
But I cannot load the XLSX file and read the hyperlink just as my question said.
And If I just load and re-save the XLSX file, ALL existing hyperlinks will be lost. Yeah!
from openpyxl import load_workbook
xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)
wbook.save(xlsFile)
A workaround!
Use the formula with OpenPyXL.
My purpose is to append clickable cells to existing XLSX file. Since hyperlink doesn't work. I use the formula =HYPERLINK(url, displayText) instead. And luckily, the formula is not lost like previous experiment 3.
from openpyxl import load_workbook
xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)
wsheet1= wbook.get_sheet_by_name('mysheet')
cell1 = wsheet1.cell('A2')
cell1.value=r'=HYPERLINK("http://www.example.com","XXX")'
wbook.save(xlsFile)
Other (failed) options I tried:
I looked into the XlsxWriter. But it explicitly says it cannot modify existing XLSX file. So it cannot be used for appending.
I also looked into the xlrd/xlwt/xlutils, unfortunately, if you want to edit an existing excel, you have to use xlrd to load it as a read-only workbook, and then use xlutils to convert(copy) it into a writable workbook. And BANG! during the copy, something will be lost which includes the HYPERLINK formula. According to its doc string, this is a known limitation:
# Copyright (c) 2009-2012 Simplistix Ltd
#
# This Software is released under the MIT License:
# http://www.opensource.org/licenses/mit-license.html
# See license.txt for more details.
from xlutils.filter import process,XLRDReader,XLWTWriter
def copy(wb):
"""
Copy an :class:`xlrd.Book` into an :class:`xlwt.Workbook` preserving as much
information from the source object as possible.
See the :doc:`copy` documentation for an example.
"""
w = XLWTWriter()
process(
XLRDReader(wb,'unknown.xls'),
w
)
return w.output[0][1]
And also, xlwt doesn't support XLSX, only supports XLS. That's another reason I decided not to use it.

openpyxl data_only gives only a none answer when storing a variable

So basically what I am trying to do is read in some input variables from an excel workbook and write them into some Output Model cells. Then I save the workbook to try to update the data in the Output Model. Since my Output Model cells are formulas I try to reload the workbook as a read data_only and then grab those cells and store them on a separate sheet. Then I save the workbook one more time.
The problem is the values I try to grab (LS, Sales, TPLH) in the data_only loaded workbook reads out as none instead of the values that I need. I eventually want to make this into a loop to iterate over a bunch of input variables, but I wanted to try it with just one set to begin with.
If anyone knows of a better way to do this or what I am doing wrong please let me know! I appreciate any and all feedback.
Here is my code:
from openpyxl import load_workbook
wb2 = load_workbook("Z:\\PythonFiles\\testexcel.xlsx")
sh2 = wb2.get_sheet_by_name("Output Model")
sh= wb2.get_sheet_by_name('OptimizationData')
ForeCast = sh.cell(row=3, column=2).value
sh2.cell(row=3, column=6).value=ForeCast
wb2.save("Z:\\PythonFiles\\testexcel.xlsx")
wb = load_workbook("Z:\\PythonFiles\\testexcel.xlsx", data_only =True)
sh3 = wb.get_sheet_by_name("Output Model")
sh4 = wb.get_sheet_by_name("OptimizationData")
LS=sh3.cell(row=11, column=3).value
Sales = sh3.cell(row=12, column=3).value
TPLH = sh3.cell(row=13, column=3).value
sh4.cell(row=3, column=7).value=LS
sh4.cell(row=3, column=8).value=Sales
sh4.cell(row=3, column=9).value=TPLH
wb.save("Z:\\PythonFiles\\testexcel.xlsx")
Openpyxl will never calculate the result of a formula. It is entirely dependent upon another application having done that. It also means that such values are stripped from a workbook when it is passed through openpyxl. This happens as soon as you save wb2. If you want to access those values then you need to open wb in data-only mode first.