Forum Discussion
Mac: Excel 365 macro's SaveAs CSV gives "Run-time error '1004'" "Cannot access read-only document"
Woo hoo! It worked! The old "Spend an hour creating a nice detailed help request and you will be rewarded with finding the solution immediately" principle came good.
--- Update: That was yesterday. Today, we tried to use it in production, and it gave the usual 1004 error. See next reply for the latest seems-to-work solution.
--- End update
As I clicked Save for the message above, I thought of ~one~more~thing~. (See what I did there?) I changed the export file type to xlOpenXMLWorkbook which creates an xlsx file. when I ran the macro, it popped up a pop-up asking me to Grant File Access to the target directory. I granted, and the xlsx appeared. I switched the file type and suffix back to CSV, and this time I get a CSV file with no errors.
This, I believe, is a bug in Excel.
- PloughguyApr 13, 2021Copper Contributor
But wait, there's more...
The solution above is not 100% complete. I extended the macro to always save an xlsx version first, then save the csv. Each files had a slightly different base name (the first part of the file name, before the dot) to make it easy to see what is going on during testing.
Turns out, Excel ignores extensions when it is checking for a potential file name collision. It is not enough that the extension is different, the bit before the dot also has to be different. This was the case when I was testing earlier, but for the production version of the macro, I gave the xlsx and csv files matching names except for the extension. These are considered to be unique file names by every operating system I have ever worked with, but Excel gives an error (cannot access read-only document) if it is saving a file with a base name that matches an existing file with a different extension..
This version (below) of the macro seems to work (as in I cannot guarantee it will be working tomorrow, since the solution above seemed to work yesterday...)
Note that the csv path ends in ...-cs.csv and the xlsx version ends in ...-xl.xlsx to make the filenames different before the extension is added.
Some things to note while you are wrestling with this:
- It creates a new workbook containing just the sheet being saved. You need to close or delete this between test runs unless they get to the "close" line in the macro.
- To protect your sanity, remove any files that it creates between runs.
Good luck, and stay strong.
Russ
Sub saveSheetToCSV() ' ' Save the active sheet to a file in a directory determined by a named cell. ' The filename is derived from the sheet name. ' Assumes CSVPATH, FY and QTR are named cells set elsewhere. ' A bug in something means Excel does not request Grant Access for CSV, but it does for xmlx ' Therefore we save as xmlx first, then save as CSV. ' To add to the excitement, Excel will give a 1004 error if the xmlx and csv have the same name prefix - it is not enough that they have different extensions. ' Replace all spaces in sheet name with dash. This removes doubt - not required? sheetName = Replace(ActiveSheet.Name, " ", "-") ' Make a path using the sheet name, with different endings for xmlx and csv versions. csvpath = Range("CSVPATH").Value & "/" & sheetName & "-" & Range("FY").Value & "Q" & Range("QTR").Value & "-cs.csv" xmlpath = Range("CSVPATH").Value & "/" & sheetName & "-" & Range("FY").Value & "Q" & Range("QTR").Value & "-xl.xlsx" MsgBox xmlpath ActiveWorkbook.Sheets(ActiveSheet.Name).Copy ActiveWorkbook.SaveAs FileName:=xmlpath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False MsgBox csvpath ActiveWorkbook.SaveAs FileName:=csvpath, FileFormat:=xlcsv, CreateBackup:=False ActiveWorkbook.Close End Sub
- PloughguyApr 13, 2021Copper ContributorYep. Nup. Didn't even make it to tomorrow.
The macro above creates a CSV file with the correct name and contents in the expected location. Whoopee!
But...
It then:
- changes the name of the main workbook to the CSV path;
- offers to save it too with "Your changes will be lost if you don't save them.
- the message bar (below the ribbon) says "Possible data loss: Some features might be lost if you save this workbook in the comma-delimited format."
So saving a single sheet as a CSV changes the name and file type of the whole workbook. But saving a single sheet as an xlsx file leaves the name of the parent workbook unchanged.
There is something very, very sick about saving as CSV- Jonathan_B830Jul 16, 2021Copper Contributor
>>It then:
>>- changes the name of the main workbook to the CSV path;I am working on the same overall problem with saving as .csv on a Mac, and while working with your script modifications i also encountered the issue where the main workbook has its name changed.
A couple notes:
- I am working out of an XLSM, call it Master.XLSM.
- The first half of the script copies a worksheet, edits the copy, and then moves the copy into a new book.
- Second half of the script attempts to name the new book Child.csv.
Here's what happened:
- I attempted to use your code to first save as Child-xl.xlsx, then save a second time as Child-cs.csv. In my attempts, I noticed that the "-xl" and "-cs" didn't affect anything for me.
- If I run the script without the MsgBox lines, I can save the new file as Child.xslx, but once I attempt Child.csv, I get an error.
- If I run the script with the MsgBox lines, Master.XLSM gets saved under the name Child.xlsx, saving as Child.csv triggers the error, and the new file remains simply "Book1".
My guess is that, for the scenario above, when a MsgBox is triggered, the sheet containing the macro becomes the ActiveSheet. Which would explain why my PERSONAL.XLSB got corrupted when I attempted running the script from there instead of Master.XLSM.