Python win32 read/modify/store/map Name Box - python

I'm trying to do some work on a complex Excel Workbook which has a large number of variables which have been created and used using the Name Box feature. See picture attached for example/detail.
I'd like to store or change DeathRate or maybe read all the Name Boxes and create a dictionary between names and locations of the cell from outside Excel.
I'm using the win32com library in Python but I guess I could switch to another Excel reader as long as it copes with XLSX files.
Has someone come across this before?

Found the solution, see code below:
import os
from win32com.client import Dispatch #win32com is based around cells beginning at one.
app_xl = Dispatch("Excel.Application")
WORKING_DIR = os.getcwd()
excelPath = WORKING_DIR + "\SampleModel.xls"
wb = app_xl.Workbooks.Open(excelPath)
# Get Named Boxes
name_box_list = [x for x in app_xl.ActiveWorkbook.Names]
name_box_map = {x.Name:x.Value for x in name_box_list}
print name_box_list
print name_box_map
# Change Named Boxes
name_box_list[0].Name = u'NewName'
name_box_list[0].Value = u'=model!$B$5'
name_box_map = {x.Name:x.Value for x in name_box_list}

Related

How to return the PrintArea from Excel in Python

I'm trying to create a Python script (I'm using Python 3.7.3 with UTF-8 encoding on Windows 10 64-bit with Microsoft Office 365) that exports user selected worksheets to PDF, after the user has selected the Excel-files.
The Excel-files contain a lot of different settings for page setup and each worksheet in each Excel-file has a different page setup.
The task is therefore that I need to read all current variables regarding page setup to be able to assign them to the related variables for export.
The problem is when I'm trying to get Excel to return the current print area of the worksheet, which I can't figure out.
As far as I understand I need to be able to read the current print area, to be able to set it for the export.
The Excel-files are a mixture of ".xlxs" and ".xlsm".
I've tried using all kind of different methods from the Excel VBA documentation, but nothing has worked so far e.g. by adding ".Range" and ".Address" etc.
I've also tried the ".UsedRange", but there is no significant difference in the cells that I can search for and I can't format them in a specific way so I can't use this.
I've also tried using the "IgnorePrintAreas = False" variable in the "ExportAsFixedFormat"-function, but that didn't work either.
#This is some of the script.
#I've left out irrelevant parts (dialogboxes etc.) just to make it shorter
#Import pywin32 and open Excel and selected workbook.
import win32com.client as win32
excel = win32.gencache.EnsureDispatch("Excel.Application")
excel.Visible = False
wb = excel.Workbooks.Open(wb_path)
#Select the 1st worksheet in the workbook
#This is just used for testing
wb.Sheets([1]).Select()
#This is the line I can't get to work
ps_prar = wb.ActiveSheet.PageSetup.PrintArea
#This is just used to test if I get the print area
print(ps_prar)
#This is exporting the selected worksheet to PDF
wb.Sheets([1]).Select()
wb.ActiveSheet.ExportAsFixedFormat(0, pdf_path, Quality = 0, IncludeDocProperties = True, IgnorePrintAreas = False, OpenAfterPublish = True)
#This closes the workbook and the Excel-file (although Excel sometimes still exists in Task Manager
wb.Close()
wb = None
excel.Quit()
excel = None
If I leave the code as above and try and open a test Excel-file (.xlxs) with a small PrintArea (A1:H8) the print function just gives me a blank line.
If I add something to .PrintArea (as mentioned above) I get 1 of 2 errors:
"TypeError: 'str' object is not callable".
or
"ps_prar = wb.ActiveSheet.PageSetup.PrintArea.Range
AttributeError: 'str' object has no attribute 'Range'"
I'm hoping someone can help me in this matter - thanks, in advance.
try
wb = excel.Workbooks.OpenXML(wb_path)
insead of
wb = excel.Workbooks.Open(wb_path)
My problem was with a german version of ms-office. It works now. Check here https://social.msdn.microsoft.com/Forums/de-DE/3dce9f06-2262-4e22-a8ff-5c0d83166e73/excel-api-interne-namen?forum=officede

Is there a way for 2 scripts to write to the same file?

I have limited python experience, but determined to learn. I am trying to create a script that would write some data inputs to excel until stopped. It is very straightforward when a single person is using it but the problem is that 2 people will be using it at once.
I am thinking about making it simple and just having 2 exact same scripts running at the same time, but the problem comes in when the file is going to be saved. If I have two files being saved with the same name, one is going to overwrite the other and the data will be lost. Is there a way to have the scripts create files with different names without having to manually change the code? (This would eventually be scaled to up to 20 computers running it)
The loop looks like:
import xlwt
from xlwt import Workbook
wb = Workbook()
s1 = wb.add_sheet('Sheet 1')
data = []
while user != '0':
user = input('Scan ID Badge: ')
data.append(user)
order = input('Scan order: ')
data.append(order)
item = input('Scan item barcode: ')
data.append(item)
for i in range(len(data)):
s1.write(row,i,data[i])
wb.save('OrderData.xls')
data = []
row += 1
If you want to use a tabular form of data storage anyways, you could switch to a real database and on interval create an excel-like summary of the db file.
If you know all of the users using this script will be using machines with different network names, you could include the computer name in the XLS name:
import platform
filename = 'AssociateEfficiencyTemp-' + platform.node() + '.xls'
# ...
wb.save(filename)
(You can also use getpass.getuser() to (try and) get the username of the user running the script.)
You can then write another script that reads all of the separate files (glob.glob('AssociateEfficiencyTemp-*.xls') etc.) and combines them.
(I would suggest using another format than .xls for the intermediary files though, such as plain text files of JSON lines.)

Opening up Excel via Python on macOS

So I coded up a program that extracts data from certain websites and then exports said data to a temporary excel file(which is created at the given path if not already existing). Below is the code for the main function. The part I am having trouble with is starting with book = xlwt.Workbook() but I wanted to include everything to provide the full situation. I coded up the program on a Windows 10 computer, and everything worked fine. However, I need to change this to work on a mac. I know with the mac I'm getting to at least the browser.close() part but after that, I have no idea if anything is working. I am unsure if I am writing into an Excel file at all in the first place, but mostly I am having trouble figuring out how to find the path of the excel file and launching the file itself. Can anyone help me figure out how to do the same thing I do below but just for a mac instead??
def main():
now = datetime.datetime.now()
option = selenium.webdriver.ChromeOptions()
browser = selenium.webdriver.Chrome()
keyword = None
urlList = None
# two different lists of data I scrapped
wi = webInfo(browser, keyword)
mi = mobileInfo(browser, keyword)
urlList = wi+mi
browser.close()
book = xlwt.Workbook()
sheet1 = book.add_sheet('sheet1')
for i in range(len(urlList)):
for j in range(len(urlList[i])):
sheet1.write(i, j, urlList[i][j])
name = "random.xls"
book.save(name)
book.save(TemporaryFile())
excelFile = "C:/Users/me/PycharmProjects/test/random.xls"
excelEx = r"C:/Program Files/Microsoft Office/root/Office16/EXCEL"
subprocess.Popen([excelEx, excelFile])
You could use os module to deal with paths in mac if you have limited access to macOS.
For example let's assume that you want to put the output excel file into the same directory as your python file, then,
import os
os.chdir(os.getcwd())
name = "random.xls"
book.save(name)
excelFile = os.path.abspath('random.xls')
# just try without these lines first and open file manually
excelEx = "You need to show the excel executable at this point"
subprocess.Popen([excelEx, excelFile])

Python: Using win32com (or other module) to adjust print properties of excel file

i need to print an excel sheet and need to do it using some kind of python script. So far i have used win32com in my script and i also got it done to get a printout using the following code:
import win32com.client
o = win32com.client.Dispatch("Excel.Application")
o.Visible = 1
wb = o.Workbooks.Open(r'C:\test.xlsx')
ws = wb.Worksheets[1]
ws.PrintOut()
Unfortunately before i actually print the excel-sheet i need to adjust the print settings of this sheet/file: change format to landscape and change to small/narrow margin.
I have found this site that might contain just what i need:
https://msdn.microsoft.com/en-us/library/aa220363(v=office.11).aspx
Unfortunately so far i have not been able to change the desired print properties. I hope someone can help me with this or at least get me headed into the right direction.
You can edit the print settings using the PageSetup Method (https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2003/aa173425%28v%3doffice.11%29). Does not seem to have a narrow/wide/normal margin setting as you normally see in the excel application, but you can specify the margins yourself.
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesTall = 1
ws.PageSetup.FitToPagesWide = 1
ws.PageSetup.PrintArea = print_area
ws.PageSetup.LeftMargin = 25
ws.PageSetup.RightMargin = 25
ws.PageSetup.TopMargin = 50
ws.PageSetup.BottomMargin = 50
wb.ExportAsFixedFormat(0, path_to_pdf)
I am using ExportAsFixedFormat, but I guess this should work for PrintOut() too.
Reference: Print chosen worksheets in excel files to pdf in python
EDIT:
The FitToPagesTall (fits all rows on one page) and FitToPagesWide (fits all columns on one page) settings will mess up your eventual print area if you have them both set to True. You will need to specify at least one of them as False to see your margin settings take effect.
ws.PageSetup.FitToPagesTall = False
ws.PageSetup.FitToPagesWide = 1

Specify range as only selecting filled cells/ending at empty cell Python

Is there a way, using win32com, to specify that Python only selects/copies/pastes/autofills/etc a range that stops when it reaches an empty cell?
i.e.
Range(A1:A%End)
Certainly open to xlrd library suggestions, but my entire script is already using win32com. Thanks for any tips folks!
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
source = excel.Workbooks.Open("C:\source")
excel.Range("A:AA").Select()
excel.Selection.Copy()
copy = excel.Workbooks.Open("C:\copy")
excel.Range("E:AE").Select()
excel.Selection.PasteSpecial()
You can get the last non-emtpy cell via
XlDirectionDown = 4
last = wb.Range("A:A").End(XlDirectionDown)
range = wb.Range("A1:A"+str(last))
The XlDirectionDown is an XlDirection enum item (xlDown), you can also get its value from COM by dispatching via EnsureDispatch:
xlApp = win32com.client.gencache.EnsureDispatch('Excel.Application')
import win32com.client.constants as cc
XlDirectionDown = cc.xlDown
First line builds the type library for Excel for win32com, which makes constants available.

Categories

Resources