Perl - Changing Excel Worksheet name - excel

In a perl script I am writing, I am trying to find a way to open an existing excel spreadsheet, change the name of the first worksheet, and save it. It would seem like a simple task but I haven't found a simple way to do it.
Spreadsheet::WriteExcel can easily change worksheet name, but it seems like it can't read in an existing excel file.
Another constraint is that the perl module I use shouldn't need installation. I can work around this if there's no good option, but it would make things more complicated.
Edit: I am using ActivePerl 5.18, so modules included in this are ideal.

The only way of doing this while preserving everything else in the Excel file is to use Win32::OLE.
That requires having Excel installed on the computer on which the program will be run, and, of course, only works on Windows.
If you can't do that, you will have to read the Excel file, and write out the contents to another file, changing the name of the worksheet in the process. Depending on exactly what you have in the source Excel file, this can get rather involved rather fast.
See also "How can I merge two Excel (xls) files in Perl or batch?" and "In Perl, how can I copy a subset of columns from an XLSX work sheet to another?"

Related

Docx4J Generated XLSX file is always corrupt

TL;DR: Excel Workbook generated by Docx4J always says corrupted but I can't determine what Excel doesn't like about the underlying XML, let alone how to fix it.
My use case is as follows:
I am trying to produce an excel workbook with charts and graphs automatically on a regular basis. Only the raw data will change but everything else will dynamically update as the raw data is changed.
So I built an excel workbook which has a number of charts and graphs being generated by a sheet of raw data. I am using it as a template. All values of the raw data are numeric. The intent was to use Docx4J to read this 'template' and to populate the raw data sheet, then save it as a new file whereupon opening will initiate the recalculation and the charts and graphs will update. Since I am new to Docx4j, I basically decided to do baby steps by first seeing if I could open and read the contents of the cells; which I could. So far so good. I also could change the values of the cells but I could only verify this programatically by writing out to the console the location and value before a change, then the location and value after the change (ex. A1=45 followed by A1=55).
My problem starts when I try to open the resulting file. It generates, looks to be about the right size but Excel claims it is corrupted. It does try to recover what it can, but ultimately fails and the workbook won't even open. For troubleshooting, I opened up the generated xlsx and confirmed all the various XML files that make up an xlsx file were present and readable so I am concluding either something is missing or some part of the XML coming out the other side is not what Excel wants. Further troubleshooting involved creating an empty workbook (no data, 1 sheet) as my 'template', opening it and then saving it back to the file system with a different name and simply trying to see if I could open it in Excel but no dice. This has me ruling out anything to do with my attempts to write or add data to the sheet.
Relevant Environment Information:
'template' workbook is being generated on a Windows 10 64bit machine
My docx4j code is executing on a Debian 10 Linux machine running OpenJDK 11.0.4
My version of Excel both to create the 'template' and open the copy is Excel for Office365
I am running Docx4J v11.1.3 but I also tried with v8.1.5(both cases I had to use the Reference Implementation of JAXB to get around a marshalling error when trying to save)
I did see another post on Stackoverflow here about an issue related to fonts in Linux environments so I made sure to install the MS TT Corefonts but it didn't help my problem.
I ran the entire unzipped directory through BeyondCompare and there are some differences but I don't know which are just artifacts of the two different OS' or even which differences matter. Mostly they are:
small differences in file size
boolean values showing as "1", "yes", or "true" but not the same way for both files
namespaces and attributes in one file but not the other
Sheet1 from my blank workbook, before and after
All ideas are welcome.
Please try the just-released docx4j 8.1.6, which fixes handling of xlsx files created by recent releases of Excel. This was https://github.com/plutext/docx4j/issues/389

Macro doesn't work one only one of 10 computers [duplicate]

I have a simple excel VBA that is referring multiple files and copying information across to a master before processing. While building this on my own system a workbook reference (working perfectly fine) was written as:
Workbooks("key").Sheets("Sheet1").Range("A1:X57").Copy
Here key is a .xlsx file
While using this in another system this does not work and it explicitly requires the file extension in every call.
Workbooks("key.xlsx").Sheets("Sheet1").Range("A1:X57").Copy
It would not be extremely difficult for me to make this change although I wanted to understand why this is happening and can I define an Option (guessing!) that would not require me to do so?
Why is there difference in behaviour across systems while running the same script?
Any help would be much appreciated. For me this seems like VBA having a mind of its own.
If the key.xlsx file is saved on both systems, including the file extension when referring to the Workbook objects is the safer option because of Windows hide extensions setting:
The Workbooks Collection Object
If the hide extensions setting is not in effect (meaning that
extensions are indeed displayed in Windows), you must include the xls
extension when you reference a workbook in the Workbooks collection.
For example, if you have open a workbook named Book1.xls, you must use
Workbooks("Book1.xls").Activate
rather than
Workbooks("Book1").Activate
to refer to the Book1 workbook. The second line of code above, without
the xls extension, will fail with an error 9, Subscript Out Of Range,
because there is no workbook with the name Book1. If the hide
extensions setting is effect, you can omit the xls extension and use
either of the following lines of code.
Workbooks("Book1").Activate
Workbooks("Book1.xls").Activate
These lines of code assume that you do not have open both an unsaved
workbook with the name Book1 and a saved workbook with the name
Book1.xls. With the hide extensions setting enabled (so that
extensions are hidden in Windows), the two lines of code above are
functionally equivalent. As a matter of good programming practice, you
should always include the xls extension in a workbook name. This
ensures that you reference the correct workbook regardless of the
value of the hide extensions property.
More details from cpearson.com for File Extensions And Their Implications In VBA Coding

how do I get the link name from Excel or VBA

I'd like to have my spreadsheet behave differently depending on how I call it.
From file explorer I can double click on either "UHF-test.xlsm" or its shortcut, "VHF-test.lnk". From VBA or an Excel formula, how do I determine which one was used?
If I can't determine the link name, is there another way to pass information in the command line, something like this BAT file
start "\B" EXCEL \\qcy-win10-it-2\TDS-repository\TDS-UAXTED.xlsm -VHF
The BAT file solution works fairly well, it's a very small file where I can embed some options for running macros. A small downside is that the Excel PATH is not normally in the system execution PATH and needs to be added.
The goal is toI write and maintain one only macro-enabled spreadsheet stored in a network location but with the ability to allow multiple users to use it with different products and parameters without being prompted by a macro on startup.
I still prefer determining the shortcut name if someone has that solution.

Batch save pictures from multiple excel files in a folder

I have about 10000 excel files, that in a specific cell of all of them there is a picture. I need a script to read all files and save the picture with the same name of the excel files in a folder.
Could you please help with that?
Thanks.
This method is based on a number of assumptions:
All the files (10000) are located in a know folder,
All files are named according to a paradigm that can be reproduced programmatically (if not, you can get the list of files within the folder, store the list within an array, and loop through the array),
Pictures are always within the same worksheet or, if in more than one, the names of the worksheets can be reproduced programmatically,
The filenames to be used to save the pictures can match (at least as a seed) the one of the Excel the pictures are extracted,
You will manage to write some basic VBA.
Note that for the VBA you have at least two options:
Write it within an EXCEL that will only serve as the extraction engine, or
Write it as a stand-alone file and run it via DOS commands.
The VBA logic:
Create the outer loop that processes a single file,
Within the outer loop, generate the name of a file to be open,
Open the file using Workbooks.Open VBA function,
Select the worksheet and the cell containing the picture,
Use the Workbook.SaveAs to save the picture (you will need to specify the type of file to be used, e.g. .bmp).
As a simple and very efficient tool to get the code (at least) partially generated by Excel, you can RECORD a MACRO for each action and then stop recording. You will see the code generated (you will need to access the VBA mode). You can copy-paste the generated code into your development (you might need to do some simple adaptations though).
That's it.
Hope you manage. Good luck!!

Delete specific Excel sheet without ActiveX

I'm currently writing a conversion function that takes data and creates an .xls file where part of the data becomes the sheet names.
My problem is, xlswrite automatically creates 3 default sheets with default names when it creates a new Excel file. Of course, these usually don't match the names in my data, so after my conversion is done, my Excel file looks almost fine, it simply has 3 leading sheets which are not supposed to be there.
Is there a way, without using ActiveX, to either stop xlswrite from creating those sheets in the first place, or delete them afterwards?
I just found out xlswrite actually uses AxtiveX internally, so the answer is
No, there is no way.
Just use ActiveX.
I made a copy of a template Excel file with a single named sheet from the program directory to the current directory, and then write to this file.
Use
fileparts(mfilename('fullpath'))
to get the path to the program file.

Resources