【问题标题】:Working Around the Workbooks.Open Bug in VBA围绕工作簿工作。在 VBA 中打开错误
【发布时间】:2014-02-04 19:16:40
【问题描述】:

我正在尝试将数据从一个唯一工作簿传输到另一个唯一工作簿(即文件名是静态的)。我找到了一些示例代码,它创建了 2 个工作簿类型的变量(每个变量代表一个示例工作簿),然后将这些变量设置为等于 Workbooks.Open("Filename")。我尝试实现它只是发现我的代码在第一个 workbook.open("filename") 变量定义后立即停止执行。在寻找答案后,我意识到这是 VBA 中的一个错误,它是由错误检测到按下 Shift 键而造成的。 Microsoft 的支持网站上有一些代码,如果按下 shift 键,基本上不会让您的代码运行。我实现了这段代码,果然,Shift 键被检测为被物理按下,而实际上并非如此。到目前为止,这似乎是我在这个主题上找到的唯一可用的“帮助”。我似乎无法找到 workbooks.open 的替代方法来将我的工作簿变量设置为等于唯一文件路径。首先,是否有针对此错误的解决方法,以便不会检测到 Shift 键被按下?或者,第二,是否有另一种方法可以在不使用 workbooks.open 功能的情况下将我的工作簿变量设置为等于特定文件路径?

提前感谢您的帮助。

'Declare API
Declare Function GetKeyState Lib "User32" (ByVal vKey As Integer) As Integer
Const SHIFT_KEY = 16

Function ShiftPressed() As Boolean
'Returns True if shift key is pressed
    ShiftPressed = GetKeyState(SHIFT_KEY) < 0
End Function

Public Sub Initialization()
    Do While ShiftPressed()
        Application.ScreenUpdating = False
        DoEvents
        'Public Variable Definition
        'Set Tracking = Workbooks.Open("\\Server2013\NETWORK_SHARED\QC SHARED\P&Q Tracking New Template.xls")
        Set Tracking = Workbooks.Open("\\Qc\shareddocs\P&Q Tracking New Template.xls")
        'Set Data = Workbooks.Open("\\Server2013\NETWORK_SHARED\QC SHARED\Production & Quality Raw Data.xls")
        Set Data = Workbooks.Open("\\Qc\shareddocs\Production & Quality Raw Data.xls")
        DataLastRow = Data.Sheets("P&Q Raw Data").UsedRange.Rows.Count
        WS_Count = Tracking.Worksheets.Count
        Day_Array() = Array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
        Name_Array() = Array("Angel", "Tony", "Bandy", "Jorge", "Ray")
        'Unprotect Sheets
        For WS_Iter = 1 To WS_Count
            With Tracking.Worksheets(WS_Iter)
                .Activate
                .Unprotect
            End With
            'Tracking.Worksheets(WS_Iter).Activate
            'Tracking.Worksheets(WS_Iter).Unprotect
            'ActiveSheet.Unprotect
        Next WS_Iter
        'Clear Contents
        Sheets("P&Q Weekly Summary").Activate
        For WL_Row_Num = 24 To 72 Step 12
            Sheets("P&Q Weekly Summary").Range(Cells(WL_Row_Num, 3), Cells(WL_Row_Num + 4, 6)).ClearContents
            Sheets("P&Q Weekly Summary").Range(Cells(WL_Row_Num, 10), Cells(WL_Row_Num + 4, 10)).ClearContents
        Next WL_Row_Num
        'Reprotect Sheet 1
        Sheets("P&Q Weekly Summary").Protect UserInterfaceOnly:=True
        'Variable Initialization
        WL_Row_Num = 0
        WS_Num = 0
        SBName_Row_Num = 12
        Name_Row_Num = 20
        Weekly_Score_Row = 24
        'Userform Input
        Vacation_Options_Form.Show
    Loop
End Sub

我对代码进行了一些修改,发现了一个有趣的观察结果。下面是我的精简代码的 sn-p:

Public Sub Initialization()
Application.EnableEvents = True
Application.ScreenUpdating = False
Set Data = Workbooks.Open("\\Qc\shareddocs\Production & Quality Raw Data.xls")
MsgBox "The Data Workbook Is Now Open."
Set Tracking = Workbooks.Open("\\Qc\shareddocs\P&Q Tracking New Template.xls")
MsgBox "The Tracking Workbook Is Now Open."
DataLastRow = Data.Sheets("P&Q Raw Data").UsedRange.Rows.Count
WS_Count = Tracking.Worksheets.Count
Day_Array() = Array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
Name_Array() = Array("Angel", "Tony", "Bandy", "Jorge", "Ray")

经过进一步的实验,我意识到如果我注释掉 Tracking 工作簿定义,代码会在 Data 工作簿声明之外执行,但如果我不注释掉,则不会在 Tracking 工作簿声明之外执行。跟踪工作簿是我最初打开的工作簿,如果有影响的话。我已将问题隔离到此。如果您尝试打开的工作簿已经打开并且是您从中执行代码的主要工作簿,则 Workbooks.Open 命令似乎不起作用。这看起来对吗?这是错误吗?我要做的就是正式将我的工作簿声明为唯一变量。除了 Workbooks.Open 还有其他方法吗?请帮忙。谢谢。

【问题讨论】:

  • 我想我已经回答了一个类似的问题,比如你的问题……有一刻。让我再次确认...我变老了,你看:D
  • 找到了。 THIS 有帮助吗?
  • @jlynn303 - 这将有助于显示您的实际代码,包括 Shift 键解决方法。
  • 我认为 OP 可能会过早地认为他遇到了这个错误。如果 Sid 的其他答案还没有回答这个问题,@jlynn303 正在使用的代码真的会帮助我们想出一个替代方案。
  • 我尝试了类似的线程,我意识到我没有放入'DoEvents'行代码;但是,即使在我将它放在我的 workbooks.open 代码之前,也没有任何改变。下面是我的代码。如果它的格式不正确,我深表歉意,因为我看不到如何在评论中添加代码块。

标签: vba excel


【解决方案1】:

我最终通过完全不使用 Workbooks.Open 功能解决了这个问题。我只是将我的基本工作簿称为 ThisWorkbook 并完全避免了这个问题。我试图避免为所需的工作簿使用预定义的变量,例如 ThisWorkbook,但最终这似乎是唯一可用的,或者至少是最好的选项。

【讨论】:

    【解决方案2】:

    所以在我的情况下,问题是 open 方法没有打开文件并且没有错误,而且代码不会停止/中断。设置 objWB = Workbooks.Open(...) 只会返回 Nothing。

    我认为 open 方法仅在您从函数中调用时才起作用。当我在方法中使用它时,它按预期工作。

    我的解决方法是使用外部应用程序。就像用 VB 或 C# 编写代码一样。

    这是从多个文件获取行数的快速 C# 代码:

    using Microsoft.Office.Interop.Excel;
    using System;
    
    namespace ExcelRowCounter
    {
        class Program
        {
            static void Main(string[] args)
            {
                foreach (string arg in args)
                {
                    Console.WriteLine("{0}|{1}", arg, GetWorkbookRowCount(arg, false));
                }
                Console.WriteLine("Completed");
                Console.ReadKey();
            }
    
            static int GetWorkbookRowCount(string strWorkbookPath, bool booAllSheets)
            {   
                int retVal = 0;
                try
                {
                    Application objExcelApplication = new Application();
                    objExcelApplication.Visible = false;
                    Workbook objWorkBook = objExcelApplication.Workbooks.Open(strWorkbookPath, ReadOnly: true);
    
                    foreach (Worksheet objSheet in objWorkBook.Sheets)
                    {
                        retVal = objSheet.Rows.SpecialCells(XlCellType.xlCellTypeLastCell).Row;
                        if (booAllSheets == false)
                        {
                            break;
                        }
                    }
    
                    objWorkBook.Close(false);
                    objWorkBook = null;
    
                    objExcelApplication.Quit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Bah! Find code and debug!");
                    Console.WriteLine("Filepath: " + strWorkbookPath);
                    Console.WriteLine("Error: " + ex.Message);
                }
                return retVal;
            }
        }
    }
    

    问题示例:

    Function GetWorkbookRowCount(ByVal strWorkbookPath As String) As Integer
    
        Dim retVal As Integer: retVal = -1
        Dim objWorkBook As Workbook
    
        Set objWorkBook = Excel.Workbooks.Open(Filename:=strWorkbookPath, ReadOnly:=True) ' Fails to open file here
    
        If (objWorkBook Is Nothing) Then
            'Failed to open file
            Debug.Assert False
    
        Else
            retVal = objSheet.Rows.SpecialCells(xlCellTypeLastCell).Row
    
            objWorkBook.Close
            Set objWorkBook = Nothing
    
        End If
    
        GetWorkbookRowCount = retVal
    
    End Function
    

    (部分,因为它在函数中不起作用!)解决方案示例:

    Sub PrintWorkbookRowCount()
    
        Dim retVal As Integer: retVal = -1
        Dim strWorkbookPath As String: strWorkbookPath = "c:\temp\exportFile.csv"
        Dim objWorkBook As Workbook: Set objWorkBook = Workbooks.Open(Filename:=strWorkbookPath, ReadOnly:=True)
    
        retVal = objSheet.Rows.SpecialCells(xlCellTypeLastCell).Row
    
        objWorkBook.Close
        Set objWorkBook = Nothing
    
        Debug.Print (strWorkbookPath & "|" & retVal)
    
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-13
      • 2012-10-26
      • 2018-01-25
      • 1970-01-01
      相关资源
      最近更新 更多