web-dev-qa-db-de.com

Wie verwende ich VBA SaveAs, ohne die aufrufende Arbeitsmappe zu schließen?

Ich möchte:

  • Führen Sie die Datenmanipulation mithilfe einer Vorlagenarbeitsmappe durch
  • Speichern Sie eine Kopie dieses Arbeitsbuchs als .xlsx ( SaveCopyAs lässt Sie keine Dateitypen ändern, andernfalls wäre dies großartig)
  • Originalvorlage anzeigen (nicht die "gespeicherte als")

Die Verwendung von SaveAs macht genau das, was erwartet wird. Es speichert die Arbeitsmappe, während die Makros entfernt werden, und zeigt mir die Ansicht der neu erstellten Arbeitsmappe "SavedAs". 

Dies bedeutet leider:

  • Ich sehe meine makroaktivierte Arbeitsmappe nicht mehr an, wenn ich sie nicht erneut öffne
  • Die Codeausführung wird an diesem Punkt angehalten, weil
  • Alle Makroänderungen werden verworfen, wenn ich das Speichern vergesse.

Gibt es eine Möglichkeit, dies zu tun?

'current code
Application.DisplayAlerts = False
templateWb.SaveAs FileName:=savePath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
templateWb.Activate
Application.DisplayAlerts = True

'I don't really want to make something like this work (this fails, anyways)
Dim myTempStr As String
myTempStr = ThisWorkbook.Path & "\" & ThisWorkbook.Name
ThisWorkbook.Save
templateWb.SaveAs FileName:=savePath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
ActiveWorkbook.Close
Workbooks.Open (myTempStr)

'I want to do something like:
templateWb.SaveCopyAs FileName:=savePath, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False 'SaveCopyAs only takes one argument, that being FileName

Beachten Sie auch, dass SaveCopyAs es mir erlauben wird, es als einen anderen Typ zu speichern (dh templateWb.SaveCopyAs FileName:="myXlsx.xlsx"). Dies führt beim Öffnen zu einem Fehler, da es jetzt ein ungültiges Dateiformat hat.

12
enderland

Ich tat etwas Ähnliches, was Siddharth vorschlug, und schrieb eine Funktion, um dies zu tun, einige der Ärgernisse zu behandeln und mehr Flexibilität zu bieten.

Sub saveExample()
    Application.ScreenUpdating = False

    mySaveCopyAs ThisWorkbook, "C:\Temp\testfile2", xlOpenXMLWorkbook

    Application.ScreenUpdating = True
End Sub

Private Function mySaveCopyAs(pWorkbookToBeSaved As Workbook, pNewFileName As String, pFileFormat As XlFileFormat) As Boolean

    'returns false on errors
    On Error GoTo errHandler



     If pFileFormat = xlOpenXMLWorkbookMacroEnabled Then
        'no macros can be saved on this
        mySaveCopyAs = False
        Exit Function
    End If

    'create new workbook
    Dim mSaveWorkbook As Workbook
    Set mSaveWorkbook = Workbooks.Add

    Dim initialSheets As Integer
    initialSheets = mSaveWorkbook.Sheets.Count


    'note: sheet names will be 'Sheet1 (2)' in copy otherwise if
    'they are not renamed
    Dim sheetNames() As String
    Dim activeSheetIndex As Integer
    activeSheetIndex = pWorkbookToBeSaved.ActiveSheet.Index

    Dim i As Integer
    'copy each sheet
    For i = 1 To pWorkbookToBeSaved.Sheets.Count
        pWorkbookToBeSaved.Sheets(i).Copy After:=mSaveWorkbook.Sheets(mSaveWorkbook.Sheets.Count)
        ReDim Preserve sheetNames(1 To i) As String
        sheetNames(i) = pWorkbookToBeSaved.Sheets(i).Name
    Next i

    'clear sheets from new workbook
    Application.DisplayAlerts = False
    For i = 1 To initialSheets
        mSaveWorkbook.Sheets(1).Delete
    Next i

    'rename stuff
    For i = 1 To UBound(sheetNames)
        mSaveWorkbook.Sheets(i).Name = sheetNames(i)
    Next i

    'reset view
    mSaveWorkbook.Sheets(activeSheetIndex).Activate

    'save and close
    mSaveWorkbook.SaveAs FileName:=pNewFileName, FileFormat:=pFileFormat, CreateBackup:=False
    mSaveWorkbook.Close
    mySaveCopyAs = True

    Application.DisplayAlerts = True
    Exit Function

errHandler:
    'whatever else you want to do with error handling
    mySaveCopyAs = False
    Exit Function


End Function
5
enderland

Hier ist eine viel schnellere Methode als die Verwendung von .SaveCopyAs, um eine Kopie zu erstellen, diese Kopie dann zu öffnen und zu speichern als ...

Wie in meinen Kommentaren erwähnt, dauert dieser Vorgang ca. 1 Sekunde, um eine Xlsx-Kopie aus einer Arbeitsmappe mit 10 Arbeitsblättern zu erstellen (jeweils mit 100 Zeilen * 20 Cols Daten).

Sub Sample()
    Dim thisWb As Workbook, wbTemp As Workbook
    Dim ws As Worksheet

    On Error GoTo Whoa

    Application.DisplayAlerts = False

    Set thisWb = ThisWorkbook
    Set wbTemp = Workbooks.Add

    On Error Resume Next
    For Each ws In wbTemp.Worksheets
        ws.Delete
    Next
    On Error GoTo 0

    For Each ws In thisWb.Sheets
        ws.Copy After:=wbTemp.Sheets(1)
    Next

    wbTemp.Sheets(1).Delete
    wbTemp.SaveAs "C:\Blah Blah.xlsx", 51

LetsContinue:
    Application.DisplayAlerts = True
    Exit Sub
Whoa:
    MsgBox Err.Description
    Resume LetsContinue
End Sub
5
Siddharth Rout

Ich habe einen ähnlichen Prozess, hier ist die Lösung, die ich verwende. Der Benutzer kann eine Vorlage öffnen, Manipulationen durchführen, die Vorlage irgendwo speichern und dann die ursprüngliche Vorlage öffnen

  1. benutzer öffnet eine makrofähige Vorlagendatei
  2. manipulieren
  3. speichern Sie den Dateipfad von ActiveWorkbook (Vorlagendatei)
  4. ein SaveAs ausführen
  5. setze ActiveWorkbook (jetzt die gespeicherte Datei) als Variable 
  6. Öffnen Sie den Vorlagendateipfad in Schritt 3
  7. schließen Sie die Variable in Schritt 5

der Code sieht ungefähr so ​​aus:

    'stores file path of activeworkbook BEFORE the SaveAs is executed
    getExprterFilePath = Application.ActiveWorkbook.FullName

    'executes a SaveAs
    ActiveWorkbook.SaveAs Filename:=filepathHere, _
    FileFormat:=51, _
    Password:="", _
    WriteResPassword:="", _
    ReadOnlyRecommended:=False, _
    CreateBackup:=False

    'reenables alerts
    Application.DisplayAlerts = True


    'announces completion to user
    MsgBox "Export Complete", vbOKOnly, "List Exporter"             


    'sets open file (newly created file) as variable
    Set wbBLE = ActiveWorkbook

    'opens original template file
    Workbooks.Open (getExprterFilePath)

    'turns screen updating, calculation, and events back on
    With Excel.Application
        .ScreenUpdating = True
        .Calculation = Excel.xlAutomatic
        .EnableEvents = True
    End With

    'closes saved export file
    wbBLE.Close
1
arbitel

In Excel VBA gibt es nichts hübsches oder nettes über diesen Prozess, aber so etwas wie das unten ... Dieser Code behandelt Fehler nicht sehr gut, ist hässlich, sollte aber funktionieren.

Wir kopieren die Arbeitsmappe, öffnen und speichern die Kopie erneut und löschen dann die Kopie. Die temporäre Kopie wird in Ihrem lokalen temporären Verzeichnis gespeichert und auch von dort gelöscht.

Option Explicit

Private Declare Function GetTempPath Lib "kernel32" _
         Alias "GetTempPathA" (ByVal nBufferLength As Long, _
         ByVal lpBuffer As String) As Long

Public Sub SaveCopyAs(TargetBook As Workbook, Filename, FileFormat, CreateBackup)
  Dim sTempPath As String * 512
  Dim lPathLength As Long
  Dim sFileName As String
  Dim TempBook As Workbook
  Dim bOldDisplayAlerts As Boolean
  bOldDisplayAlerts = Application.DisplayAlerts
  Application.DisplayAlerts = False

  lPathLength = GetTempPath(512, sTempPath)
  sFileName = Left$(sTempPath, lPathLength) & "tempDelete_" & TargetBook.Name

  TargetBook.SaveCopyAs sFileName

  Set TempBook = Application.Workbooks.Open(sFileName)
  TempBook.SaveAs Filename, FileFormat, CreateBackup:=CreateBackup
  TempBook.Close False

  Kill sFileName
  Application.DisplayAlerts = bOldDisplayAlerts
End Sub
1
AndASM

Eine weitere Option (nur mit den neuesten Versionen von Excel getestet).

Die Makros werden erst gelöscht, wenn die Arbeitsmappe nach einer SaveAs.xlsx geschlossen wird, sodass Sie zwei SaveAs schnell hintereinander ausführen können, ohne die Arbeitsmappe zu schließen.

ActiveWorkbook.SaveAs FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False, ConflictResolution:=xlLocalSessionChanges
Application.DisplayAlerts = True

Hinweis: Sie müssen die Variable DisplayAlerts deaktivieren, damit nicht die Warnung angezeigt wird, dass die Arbeitsmappe beim zweiten Speichern bereits vorhanden ist.

0
OSKM