You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用VBS读取被Excel打开的UTF-8编码CSV文件内容?

读取被Excel锁定的UTF-8文件解决方案

核心问题分析

Excel打开文件时会施加独占式锁定,导致ADODB.Stream默认的独占打开模式失败;而FileSystemObject.OpenTextFile虽能绕过锁定,但仅支持UTF-16编码,无法直接处理UTF-8内容。以下是几种可行的解决方法:


方法1:修改ADODB.Stream的共享模式

通过指定Open方法的模式参数,允许共享读取,即可绕过Excel的独占锁定:

Set oTxtStream = CreateObject("ADODB.Stream")
oTxtStream.CharSet = "utf-8"
' adModeRead(3) + adModeShareDenyNone(16):以共享读模式打开
oTxtStream.Open , 3, 16
oTxtStream.LoadFromFile(sMdmTestMetadataResults)
content = oTxtStream.ReadText
oTxtStream.Close
Set oTxtStream = Nothing

说明:adModeShareDenyNone参数允许其他进程(如Excel)保持文件打开状态,同时我们可以读取内容。


方法2:通过Windows API直接读取并转码

如果ADODB的方法仍有问题,可调用Windows API以共享模式打开文件,读取二进制内容后再转成UTF-8字符串:

Option Explicit

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
    ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    lpSecurityAttributes As Long, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long _
) As Long

Private Declare Function ReadFile Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToRead As Long, _
    lpNumberOfBytesRead As Long, _
    lpOverlapped As Long _
) As Long

Private Declare Function CloseHandle Lib "kernel32" ( _
    ByVal hObject As Long _
) As Long

Private Declare Function GetFileSize Lib "kernel32" ( _
    ByVal hFile As Long, _
    lpFileSizeHigh As Long _
) As Long

Const GENERIC_READ = &H80000000
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const OPEN_EXISTING = 3

Function ReadLockedUTF8File(filePath As String) As String
    Dim hFile As Long, fileSize As Long
    Dim buffer As String, bytesRead As Long
    
    ' 以共享读写模式打开文件,允许Excel同时持有锁
    hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
    
    If hFile = -1 Then
        ReadLockedUTF8File = ""
        Exit Function
    End If
    
    ' 获取文件大小
    fileSize = GetFileSize(hFile, 0)
    If fileSize = 0 Then
        CloseHandle hFile
        ReadLockedUTF8File = ""
        Exit Function
    End If
    
    ' 读取二进制内容
    buffer = String(fileSize, Chr(0))
    ReadFile hFile, buffer, fileSize, bytesRead, 0
    CloseHandle hFile
    
    ' 将二进制流转成UTF-8字符串
    Dim stream As Object
    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 1 ' 二进制模式
    stream.Open
    stream.Write buffer
    stream.Position = 0
    stream.Type = 2 ' 文本模式
    stream.CharSet = "utf-8"
    ReadLockedUTF8File = stream.ReadText
    stream.Close
    Set stream = Nothing
End Function

' 使用示例
Dim content As String
content = ReadLockedUTF8File("C:\LOCAL\Jonas\resources\xls\MdmTestMetadata.csv")

说明:API直接操作文件底层,绕过了VBS内置对象的锁定限制,再通过ADODB.Stream完成UTF-8转码,完美适配需求。


方法3:直接访问已打开的Excel工作簿(针对Excel格式文件)

如果目标文件是Excel格式(.xls/.xlsx),可以直接连接到已运行的Excel实例读取内容,完全避开文件锁:

Set xlApp = GetObject(, "Excel.Application")
Set xlBook = xlApp.Workbooks("MdmTestMetadata.xlsx") ' 仅需文件名,无需路径
Set xlSheet = xlBook.Sheets(1)
' 读取整张表内容(可按需调整范围)
content = xlSheet.UsedRange.Value

说明:该方法仅适用于Excel文件,无需读取磁盘文件,直接获取内存中的工作簿数据。


内容的提问来源于stack exchange,提问作者Lukas Doubek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:46:01