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!!
Related
I have a node project where I need node to create a new XLSM file using an existing XLSM file as a template. The template contains a great deal of styling, images, and VBA. The application simply inserts values into a few cells and saves the new file with a discreet name.
I have tried XLSX and ExcelJS npms to accomplish this. Both fail in different ways:
ExcelJS: Doesn't seem to support writing XLSM files at this time. Attempting to do so results in a corrupt file.
XLSX: I've not been able to create a true copy of the template. It's missing formatting and VBA, among other things. This is the very basic code I'm starting with:
const templatePath = "C:/Users/rapsputinforever/Desktop/template.xlsm"
const directory = "C:/Users/rapsputinforever/Desktop"
const workbook = XLSX.readFile(templatePath);
// will insert data to some cells here
XLSX.writeFile(workbook, directory + '/copy.xlsm');
I know this package has a variety of options which don't seem related to the issue I'm having and helpful toward accomplishing what seems, on the surface, a very simple task:
Read Template
Add Values to Cells
Write as New File keeping all VBA, styling, and et cetera
I'm willing to look into other packages, libraries, even other technologies. This tool is part of the back-end of a React app, however I'm not sure React can accomplish this. I'm open to any advice. I appreciate the help!
I successfully accomplished the issue by breaking the problem down to its constituent parts. Knowing about the nature of excel files, that they are zipped packages of XML files (source here) then it's a matter of step-wise doing the following steps:
Create a duplicate of the template XLSM file, copy has ".zip" as extension ('fs')
Un-package the zip file ('extract-zip')
read sharedStrings.XML ('fs')
Count the number of iterations of XML tag " < s i > " in sharedStrings
Example:
let stringCount = (sharedStrings.match(/<si>/g) || []).length;
read worksheet1.XML (or whatever sheet data is to be inserted)
Locate the cell by finding the tag for it. If empty the tag will resemble this:
Example:
<c r="D10" s="29"/>
Note, r = cell address, s = style tag, you want to maintain both in the next step...
Replace the empty cell tag with the shared string flag and the desired index of the new string to be inserted.
Example:
<c r="D9" s="29" t="s"><v>${stringCount}</v></c>
To summarize so far, we replace the cell XML tag with the insert string which is inserted into the sharedStrings file and referenced by the index/count of that new string. This can be interated in a loop to insert an array of values to be inserted.
Save both sharedFiles.XML and worksheet1.XML ('fs')
Package the un-zipped folder into a new archive ('archiver')
Re-name the archived folder with '.XLSM' extention ('fs')
Cleanup, kill any duplicate zip files/folders
If the work-up is correct, the sharedString index is accurate, if the style ID is maintained, and the correct script structure applied with all these asynchronous actions, the resulting file should have the desired results because the integrity of the containing VBA, Styles, Queries, Images, etc, was all maintained by creating a true copy and manipulating that copy's constituent parts.
I am a novice developer, no doubt my approach is overly lengthy and inefficient, and my understanding of why this works versus these other libraries don't rests solely upon my intuition. I believe the issue is that ExcelJS and other NPMs create a worksheet "in the buffer" which unfortunately only contains any element of the original file that that library accounts for based on XLSX files. If ExcelJS isn't looking at VBA then the new worksheet won't have VBA because when that sheet was duplicated in the buffer it only duplicated anything within its scope.
I am still very much open to more suggestions/alternatives/approaches/wisdom. I hope to fine-tune this further to be scalable: I only was able to design this for my very specific application. If I do manage to generalize this and clean up my code I will share the snippet here.
Thanks,
EDIT: Hello! As it turns out, things are not so simple! Despite not prompting errors on opening the file, the duplicate still has some background issues which is made evident if you happen to utilize Power Query to parse though said XLSM files. Additionally, any formula that references the cells filled by the node solution will not be updated on opening the file. To solve this, run this VBA:
Application.CalculateFullRebuild
This will update all formulae on every sheet. Once this file is saved the sheet should be "normal" again. The issue at hand is based on the XML file calcChain.XML.
I use VBA in Excel to pull data from different sources (mostly .csv and .xls/.xlsx files) and paste them into my data tables (in the same Excel File I have a data table for each specific data source).
Each of those files comes with different settings. I have created an specific VBA Macro for each of my data sources to process, remove and copy the relevant information of each individual file, and then I call all of the Macros from another Macro. The problem I'm having is that for one of the data sources, when using the Workbooks.Open method, I have had to set the parameter Format to "Nothing" (Format:=5). But this affects then the subsequent macros and therefore the following files are not processed correctly.
I know I have two possibilities: Either I call this macro at the end, after I've processed all the other files or; I set the Format parameter in all of my Macros to the one specific for each of the files configuration. However there must be a way to simply reset the delimiter to the default one used in my Regional Settings. Does anyone knows a solution?
Sorry if there's already a thread with this issue but I've tried looking for it and didn't find any.
Thank you in advance.
I am having a folder of 10 excel-based CSV files. Is there any method to copy the data from all these files into 1 excel
Not good with VBA, so thought to ask you guys
On a first sight, I would go for the following approach (coming up with the codes is up to you, Google is your friend):
Get a list of all file names within that directory
Iterate over every item from the above list and open the file with Workbooks.Open(...)
Copy the whole content and paste it to the additional Excel you want to manage to hold the data of all files
Repeat the steps for each file
Remember to save the last row after every paste s.t. you can continue with amending the data into the addtional Excel instead of replacing the content.
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.
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.