tags:

views:

94

answers:

2

Loading an XLS file is a bit of a pain for a quick app we're throwing together (we know about how to do that but it's not worth the time especially in C++) so we're going to take the simple approach of have the user export a CSV copy. However to save them the trouble I wondered if we can have a macro which will automatically save a CSV version whenever they save the XLS(X) in Excel 2007?

Update: Following Timores' answer, I dug in a bit and came up with this:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim Sourcewb As Workbook
    Dim Destwb As Workbook
    Dim TempFileName As String

    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With

    Set Sourcewb = ActiveWorkbook
    TempFileName = Sourcewb.FullName + ".csv"

    'Copy the sheet to a new workbook
    ActiveSheet.Copy
    Set Destwb = ActiveWorkbook

    'Save the new workbook and close it
    With Destwb
        .SaveAs Filename:=TempFileName, FileFormat:=xlCSV, ConflictResolution:=xlLocalSessionChanges
        .Close SaveChanges:=False
    End With

    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With
End Sub

This works except I can't make it force-save the CSV, rather than asking me if I want to overwrite, even after adding ConflictResolution:=xlLocalSessionChanges

+2  A: 

Original version:

In the VB editor part of Excel, select "ThisWorkbok" in the left navigation menu. In the editor on the right, select Workbook on the left drop-down, and BeforeSave on the right one.

Replace the macro by:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    ActiveWorkbook.SaveCopyAs ActiveWorkbook.FullName + ".csv"
End Sub

This will make a copy with the CSV extension.

Please note that an XLSX file cannot have a macro (you need an XLSM extension, or the older XLS one) and that users will need to have a medium or low level of security in order for the macro to run (or you have to sign the document).

Edited version:

I tested it again, after seeing the comments below. Strangely enough, it did not work like it did the first time. Here is a fixed version. Again, in the 'This Workbook' part of the macro editor:

Dim fInSaving As Boolean

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

If fInSaving Then
    Exit Sub
End If

fInSaving = True

Dim workbookName As String
Dim parentPath As String
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")

If SaveAsUI Then

    Dim result
    result = Application.GetSaveAsFilename

    If VarType(result) = vbBoolean Then
        If CBool(result) = False Then
            Exit Sub ' user cancelled the dialog box
        End If
    End If

    workbookName = fs.GetFileName(result)
    parentPath = fs.GetParentFolderName(result)
Else

    workbookName = ActiveWorkbook.name
    parentPath = ActiveWorkbook.path
End If


Dim index As Integer
index = InStr(workbookName, ".")

Dim name As String
name = Left(workbookName, index - 1)

' extension can be empty is user enters simply a name in the 'File / Save as' dialog
' so it is not computed (but hard-coded below)

' do not ask for confirmation to overwrite an existing file
Application.DisplayAlerts = False

' save a copy
ActiveWorkbook.SaveAs fs.BuildPath(parentPath, name & ".csv"), XlFileFormat.xlCSV

' Save the normal workbook in the original name
ActiveWorkbook.SaveAs fs.BuildPath(parentPath, name & ".xlsm"), XlFileFormat.xlOpenXMLWorkbookMacroEnabled
Cancel = True

Application.DisplayAlerts = True
fInSaving = False
End Sub

Private Sub Workbook_Open()

    fInSaving = False
End Sub

What is surprising is that calling ActiveWorkbook.SaveAs triggers the macro again => the global boolean to prevent infinite recursion.

Timores
Hold up there, no macros in XLSX? Or is XLSM just an excel file with macros, and nothing to worry about?
John
By definition, an XLSX never has macros. And, you are right, an XSLM simply is an XLSX with macros, that's all.
Timores
It saves a file <filename>.xslm.csv, but it's not a CSV file, looks like binary.
John
I tried again the macro at home, and it did not work, very strange. I have fixed it above.
Timores
Oops, I did not see the update of your original post. Your solution has the Application.EnableEvents = False, which eliminates my recursion problem. Please try the Application.DisplayAlerts = False to remove the overwrite confirmation.
Timores
+1  A: 

to avoid XL asking if you want to overwrite use Application.DisplayAlerts=False (and then reset back to True after the Save)

Charles Williams