【问题标题】:How to close a specific workbook from command line如何从命令行关闭特定工作簿
【发布时间】:2018-06-20 05:57:03
【问题描述】:

我有一个打开 excel 的批处理脚本,一旦打开就会自动触发宏脚本。但是我希望它在宏完成后关闭工作簿:

  1. 我尝试在 Excel 中使用 VBA 来关闭自身,但每次它都会打开一个空工作簿。如果它每天运行,它将在那里打开许多空工作簿。

工作簿.关闭

  1. 最后在批处理脚本中关闭它。我搜索但没有找到任何有效的方法。 PS 我只想关闭那个工作簿而不是终止 excel 进程。

这是我的 bat 脚本,用于打开工作簿并让它运行

  @echo off
start Excel.exe "I:\SCRIPT\IPCNewScript\ResultNew(DoNotOpen).xlsm"

这是我在打开时调用 main 的 vba 脚本

Sub WorkBook_Open()
Call Sheets("Result").main
ActiveWorkbook.Close SaveChanges:=True
'Application.Quit
End Sub

这是我的主要宏

    Sub main()
Call get_Data_From_DB
Call Reformat
Call Send_Mail
End Sub



Sub get_Data_From_DB()

   Dim cnn As ADODB.Connection
   Dim Names As New Collection
   Set cnn = New ADODB.Connection
   Set ws = ActiveWorkbook.Sheets("Result")
' get sql content

    Dim TextFile As Integer
    Dim FilePath As String
    Dim Sql As String

    'File Path of Text File
    FilePath = "I:\SCRIPT\IPCNewScript\sql.txt"

    'Determine the next file number available for use by the FileOpen function
    TextFile = FreeFile

    'Open the text file
    Open FilePath For Input As TextFile

    'Store file content inside a variable
    Sql = Input(LOF(TextFile), TextFile)


    'Close Text File
    Close TextFile


    ws.UsedRange.Delete

   ' Open a connection by referencing the ODBC driver.


    cnn.ConnectionString = "driver={SQL Server};" & _
       "server=aaaaa,2431;uid=bbbb;pwd=cccc;database=dddd"
    cnn.Open


    i = 1

    ' Find out if the attempt to connect worked.
    If cnn.State = adStateOpen Then
    'Sql = "SELECT top 10 ROW_ID, EMAIL_ADDR from TABLEA(NOLOCK)"
      'Sql = FileContent

      Set rs = cnn.Execute(Sql)

      For FieldNum = 0 To rs.Fields.Count - 1
        ws.Cells(1, i).Value = rs.Fields(FieldNum).Name
        i = i + 1
      Next

      ws.Range("A2").CopyFromRecordset rs
   Else
      MsgBox "Connection Failed"
   End If


   ' Close the connection.
   cnn.Close


End Sub

Sub Reformat()
Dim dt_Str As String, dt As Date
Set ws = ActiveWorkbook.Sheets("Result")


'Work on the first 2 head lines
'set value for the first 2 head lines
ws.Range("A2").EntireRow.Insert

i = 1
'MsgBox i
Do While ws.Cells.Item(1, i) <> ""
'MsgBox i
    If i < 5 Then
        'MsgBox ws.Cells.Item(1, i)
        ws.Cells.Item(2, i).Value = ws.Cells.Item(1, i).Value
        ws.Cells.Item(1, i).Value = ""
    Else
        dt_Str = ws.Cells.Item(1, i)
        'MsgBox i
        dt = DateValue(Left(dt_Str, 4) & "/" & Mid(dt_Str, 5, 2) & "/" & Right(dt_Str, 2))
        ws.Cells.Item(2, i).Value = Left(WeekdayName(Weekday(dt)), 3)
    End If
i = i + 1
Loop


'add color for the first 2 head lines

ws.Range(ws.Cells.Item(1, 5), ws.Cells.Item(1, i - 1)).Interior.Color = RGB(32, 74, 117)
ws.Range(ws.Cells.Item(1, 5), ws.Cells.Item(1, i - 1)).Font.Color = RGB(255, 255, 255)
ws.Range(ws.Cells.Item(1, 5), ws.Cells.Item(1, i - 1)).Font.Bold = True

ws.Range(ws.Cells.Item(2, 1), ws.Cells.Item(2, i - 1)).Interior.Color = RGB(142, 179, 226)
ws.Range(ws.Cells.Item(2, 1), ws.Cells.Item(2, i - 1)).Font.Bold = True

' add color for the call value cells

j = 5
Do While ws.Cells.Item(2, j) <> ""
    i = 3
    Do While ws.Cells.Item(i, j) <> ""
        If ws.Cells.Item(2, j) = "Sun" Then
                ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i, j)).Interior.Color = RGB(248, 214, 184)
        Else

                If ws.Cells.Item(i, j).Value = 0 Then
                    ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i, j)).Interior.Color = RGB(254, 200, 205)
                    ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i, j)).Font.Color = RGB(130, 12, 16)
                End If
        End If
        i = i + 1
    Loop
    j = j + 1
Loop


'Work on the first 4 columns

j = 1
Do While ws.Cells.Item(2, j) <> ""
    i = 3
    Do While ws.Cells.Item(i, j) <> "" And j < 4
        Application.DisplayAlerts = False
        ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i + 1, j)).Merge
        Application.DisplayAlerts = True
        ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i + 1, j + 1)).Interior.Color = RGB(217, 217, 217)
        ws.Range(ws.Cells.Item(i, j), ws.Cells.Item(i + 1, j + 1)).Font.Bold = True
        i = i + 2
    Loop
j = j + 1
Loop



'add border
Dim rng As Range

    Set rng = ws.UsedRange

    With rng.Borders
        .LineStyle = xlContinuous
        .Color = vbBlack
        .Weight = xlThin
    End With

ws.Range(ws.Cells.Item(1, 1), ws.Cells.Item(1, 4)).Borders.LineStyle = xlNone
ws.UsedRange.Font.Size = 9
ws.UsedRange.Font.Name = "Calibri"
ws.Columns.HorizontalAlignment = xlCenter
ws.Columns.AutoFit

ActiveWorkbook.SaveCopyAs ("I:\SCRIPT\IPCNewScript\Files\IPCData." & Format(Now(), "yyyymmdd-hh-mm-ss") & ".xlsx")

End Sub


Sub Send_Mail()
'Working in Excel 2002-2016
    Dim Sendrng As Range
    Set ws = ActiveWorkbook.Sheets("Result")

    On Error GoTo StopMacro

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


    'Note: if the selection is one cell it will send the whole worksheet
    Set Sendrng = ws.UsedRange

    'Create the mail and send it
    With Sendrng

        ActiveWorkbook.EnvelopeVisible = True
        With .Parent.MailEnvelope

            ' Set the optional introduction field thats adds
            ' some header text to the email body.
            '.Introduction = "All, Please check IPC call data as of today."

            With .Item
                .To = "aaa@aaa.com"
                .CC = "aaa@aaa.com"

                .BCC = ""
                .Subject = "IPC Call Data Report " & Format(Date, "YYYYMMDD")
                .Send
                'MsgBox "sending mail"
                '.Display
            End With

        End With
    End With

StopMacro:
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With
    ActiveWorkbook.EnvelopeVisible = False

End Sub

【问题讨论】:

  • 可能只需将Application.Quit 添加到您的宏中即可。
  • @YowE3K 似乎不起作用。那些空的工作簿仍然打开。这是我现在拥有的: Sub WorkBook_Open() Call Sheets("Result").main ActiveWorkbook.Close SaveChanges:=True Application.Quit End Sub
  • 是你正在运行的批处理文件,还是类似VBScript的东西?您是在现有 Excel 实例中还是在新实例中打开工作簿,还是让操作系统随意打开它?您在 main 中做什么(例如,它是否会更改活动工作簿)?如果您在问题中包含代码以便我们可以看到您在做什么,而不是根据描述猜测您可能会如何做,那么提供帮助会容易得多。
  • 实际上,我刚刚阅读了您问题的最后一部分 - “PS 我只想关闭那个工作簿而不是杀死 excel 进程” - 所以Application.Quit 没有任何用处因为它将关闭在该 Excel 实例中打开的所有个工作簿。
  • (而且,FWIW,幸运的是,Application.Quit 从未在您使用的代码中执行,因为您在到达该语句之前关闭了包含该代码的工作簿。如果它 达到Quit 声明,它将关闭该实例中的所有工作簿。)

标签: excel vba


【解决方案1】:

如果您已将 Excel 设置为默认启动一个新实例,并且可能即使您没有(我不能 100% 确定 Start 是否会重新使用现有实例,如果可以的话),您可以安全地使用Application.Quit 关闭您正在打开的唯一工作簿。

例如:

Sub WorkBook_Open()
    Sheets("Result").main
    'Don't "close" the workbook, or else it won't be open to run subsequent code
    'ActiveWorkbook.Close SaveChanges:=True
    'Save the workbook instead
    ThisWorkbook.Save
    'And then quit
    Application.Quit
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-07
    • 2017-05-11
    • 1970-01-01
    • 2014-08-01
    • 2012-08-12
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    相关资源
    最近更新 更多