两台计算机试图访问第三台计算机(服务器)中的excel文件来编写。 问题与方法

我为朋友做了一个POS系统。 POS系统是一个在带有触摸屏的台式计算机上运行的excel工作簿。 对于每个销售它访问服务器中的一个文件称为products.xlms是我更新产品数量。

当第二个terminal试图在服务器中同时访问(写入)同一个文件时,会出现问题,因为如果第一台计算机使用该文件,则第二台计算机将以只读模式打开它。

我以为我做了一个walkaround使用下面的函数,我在这里find了在计算器:

Function IsWorkBookOpen(filename As String) Dim ff As Long, ErrNo As Long On Error Resume Next ff = FreeFile() Open filename For Input Lock Read As #ff Close ff ErrNo = Err On Error GoTo 0 Select Case ErrNo Case 0: IsWorkBookOpen = False Case 70: IsWorkBookOpen = True Case Else: Error ErrNo End Select End Function 

这个函数打开文件检查是否正在使用,并closures返回一个错误。 根据错误号码,我们可以知道它是否打开。

然后,当我打开文件时,我会调用函数,如果文件已经打开,它将等待一秒钟,然后重试。

 Check: Ret = IsWorkBookOpen("PATH\products.xlsx") If Ret = True Then Application.Wait Now() + TimeSerial(0, 0, 1) GoTo Check End If Workbooks.Open("PATH\products.xlsx") 

但是,这样做对我来说并不是这样,因为交互相当快,显示它的最好方式是解释有问题的场景:

  • terminal1检查文件是否打开:打开文件,closures,没有错误,然后variables= False。 然后打开文件(第二次)来处理。

  • 如果terminal2在terminal1第一次closures时打开文件,BUM,我有一个问题,因为它会认为是未使用的(这是真的!它实际上是在这段时间内没有使用),并打开它再次(在只读模式的原因实际上正在使用)。

希望是明确的,我会尽力澄清,如果没有。 任何build议,解决方法?

谢谢

我应该注意到,我同意马克·巴特勒的看法, 通过使用Excel作为“数据库”,你肯定会对自己做出这样的努力。 然而,做了什么,所以这是我会尝试…

 Sub YourSub() Dim WB As Workbook Dim YourFile As String 'Note the ~$ in front of the file name YourFile = "C:\Users\USERNAME\Documents\~$Book1.xlsx" Do While IsFileOpen(YourFile) Loop 'File should be available to you now Set WB = Workbooks.Open(Replace(YourFile, "~$", ""), ReadOnly:=False, Notify:=False) End Sub Function IsFileOpen(fPath As String) As Boolean Dim FSO As Object 'FileSystemObject Set FSO = CreateObject("Scripting.FileSystemObject") If FSO.FileExists(fPath) Then IsFileOpen = True End If End Function 

该代码背后的逻辑是,当另一个用户打开一个Excel文件时,Excel会用〜$前缀创build一个“locking文件”。 此代码检查该锁文件是否存在,如果不存在,则会打开该文件。 这将比你发布的解决方法更有效率,每次需要检查文件是否被使用时(这不是一个大问题),它必须打开整个文件,但是当你有成千上万行的数据时,更大的交易)。

但是,这里有个大警告,有时锁文件在文件closures后不会被删除。 在这样的情况下,你的应用程序将会进入无限循环,因为locking文件将永远存在。 避免这种情况的一种方法是添加某种计数器,以便一旦循环达到您设置的最大计数(例如100000),它就会打开该文件,并检查只读的方式。

另一种select是在打开Excel文件之前立即用代码创build一个文本文件。 然后,当你完成了Excel的时候,你删除了文本文件(基本上模拟了前面提到的“locking文件”)。 这仍然是有效的,不会依赖Excellocking文件。 要做到这一点试试这个代码:

 Sub YourSub() Dim WB As Workbook Dim CheckFile As String Dim YourFile As String CheckFile = "C:\Users\USERNAME\Documents\OpenCheck.txt" Do While IsFileOpen(CheckFile) Loop 'File should be available to you now YourFile = "C:\Users\USERNAME\Documents\YourFile.xlsx" Set WB = Workbooks.Open(YourFile, ReadOnly:=False, Notify:=False) 'And then when you're done with the excel file WB.Close SaveChanges:=True Kill CheckFile End Sub Function IsFileOpen(fPath As String) As Boolean Dim FSO As Object ' FileSystemObject Dim TS As Object ' TextStream Set FSO = CreateObject("Scripting.FileSystemObject") If FSO.FileExists(fPath) Then IsFileOpen = True Else On Error GoTo AlreadyCreated Set TS = FSO.CreateTextFile(Filename:=fPath, overwrite:=False) TS.Close End If ExitFunc: On Error GoTo 0 Exit Function AlreadyCreated: IsFileOpen = True Resume ExitFunc End Function 

显然文本文件将不得不被保存到您的服务器。 我现在没有任何办法来testing这个方法,但据我所知它应该工作得很好。

build议:不要将Excel用于多用户场景。 事实上,除了电子表格以外,不要使用Excel。 这是一个非常棒的电子表格应用程序,当被迫做任何事情时都不太好。 数据库应用程序,POS系统等不是它的devise目的。 方钉,圆孔等等。

如果你热衷于使用MS Office,为什么不使用Access呢?

创build一个在每个触摸屏terminal上运行的前端应用程序,并将其连接到集中存储的后端数据库。 这将在未来为你节省很多的头痛。

问题是, Worksbooks.Open打开工作簿。 您在IsWorkbookOpen函数中打开工作簿并再次写入实际值。 你必须把这两件事情放在一起。

尝试打开它通过Workbooks.Open ReadOnly:=False, Notify:=False ,这将抛出一个错误,像你的function,你可以检查。 喜欢:

 Dim wkb As Workbook On Error Resume Next Do 'Clear existing (old) Error-Code Err.Clear 'Try to open Open "Path/test.xlsx" For Input Lock Read Write As #ff Set wkb = ActiveWorkbook If Not Err.Number = 0 Then 'Workbook is opened from another client, put Wait-code here End If 'If Workbook is open on this client, Error-code is 0 and the loop exits Loop Until Err.Number = 0 'Write the Values, use wkb On Error GoTo Errorhandler 'Its always good to catch Errors in an Errorhandler 'Write the Values, use wkb 

我不能testing错误号码,所以你必须自己检查一下。

我find了一个解决方法。 先不检查,然后打开,我将打开文件,然后检查它是否是只读模式,代码如下:

 Dim wkb As Workbook Check: 'disable alerts to skip the excel message "file been used, Open Read Only?" Application.DisplayAlerts = False Set wkb = Workbooks.Open((Config.Range("O2").Value) & "\clientdb.xlsx", Notify:=False, ReadOnly:=False) Application.DisplayAlerts = True If wkb.ReadOnly Then wkb.Close 'Wait code here Application.Wait Now() + TimeSerial(0, 0, 1) GoTo Check End If 

如果是ReadOnly,则意味着在某处打开,然后等待1秒钟,然后再次尝试,直到打开启用写入的文件。

用户Reen the Winter,谁发布了一个答案有一定的功劳,因为他帮助我思考。

谢谢大家的回应。