Microsoft Excel 无法访问文件 (Java -> cmd /c python -> Excel)
Microsoft Excel cannot access the file (Java -> cmd /c python -> Excel)
我从基于 JavaEE 的 API(cmd /c python <args>
通过 ProcessBuilder)调用以下 Python 脚本,它访问 Excel 以导出一个table 到 PDF:
import sys
import win32com.client
import pathlib
if len(sys.argv) < 5:
print("Usage: %s input.xls output.pdf worksheet range" % sys.argv[0])
exit(1)
o = win32com.client.Dispatch("Excel.Application")
o.Visible = False
wb_path = r'C:\Develop\uploadedFile_5232859756803526399.xlsx'
path_to_pdf = sys.argv[2]
worksheet_idx = sys.argv[3]
print_area = sys.argv[4]
wb = o.Workbooks.Open(wb_path)
ws = wb.Worksheets[int(worksheet_idx)]
ws.Activate()
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesTall = 1
ws.PageSetup.FitToPagesWide = 1
ws.PageSetup.PrintArea = print_area
wb.ActiveSheet.ExportAsFixedFormat(0, path_to_pdf)
wb.Close(True)
o.Quit()
wb_path = r'C:\Develop\uploadedFile_5232859756803526399.xlsx
仅用于 wb = o.Workbooks.Open(wb_path)
的测试目的(wb_path =sys.argv[1]
也不起作用),它会引发以下错误:
Traceback (most recent call last):
2022-01-13 14:46:24 INFO [utils.CMDUtils] File "C:\scripts\scriptWin.py", line 23, in <module>
2022-01-13 14:46:24 INFO [utils.CMDUtils] wb = o.Workbooks.Open(wb_path)
2022-01-13 14:46:24 INFO [utils.CMDUtils] File "<COMObject <unknown>>", line 5, in Open
2022-01-13 14:46:24 INFO [utils.CMDUtils] pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Microsoft Excel cannot access the file 'C:\Develop\uploadedFile_5232859756803526399.xlsx'. There are several possible reasons:\n\n• The file name or path does not exist.\n• The file is being used by another program.\n• The workbook you are trying to save has the same name as a currently open workbook.", 'xlmain11.chm', 0, -2146827284), None)
我做错了什么?当我在 Windows 2019 服务器上使用管理员直接在 CMD 中(通过远程桌面)调用此脚本时,它运行正常。
编辑
这是我的 Java 代码片段:
String catalinaBase = System.getProperty("catalina.base");
File logsFolder = new File(catalinaBase, "logs");
try(FileOutputStream fos = new FileOutputStream(new File(logsFolder,"cmd.log"));) {
List<String> python3 = new ArrayList<>();
if(OSUtils.isWindows()){
python3.add("cmd /c");
python3.add("python");
}else{
python3.add("python3");
}
python3.add(quoteStr(pythonScript.getAbsolutePath()));
if(params != null && params.size() > 0){
params.stream().forEach(p->{
python3.add(quoteStr(p));
});
}
ProcessBuilder pb = new ProcessBuilder(python3);
pb.redirectErrorStream(true);
Process process = OSUtils.isWindows() ?
Runtime.getRuntime().exec(String.join(" ", pb.command())) :
pb.start();
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", fos, log);
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", fos, log);
errorGobbler.start();
outputGobbler.start();
exitVal = process.waitFor(60, TimeUnit.SECONDS);
if(!exitVal){
errorGobbler.stopThread();
outputGobbler.stopThread();
process.destroyForcibly();
}
} catch (Exception e) {
e.printStackTrace();
}
StreamGobbler 与此类似:https://gist.github.com/jmartisk/6535784
设置问题。
打开DCOMCNFG,展开组件服务|我的电脑 | DCOM Config 并找到 Microsoft Excel Application -> Properties -> 在 Identity 选项卡下将其设置为“The interactive user”(仅限 RDP)或“This user”。用于后台服务。
我从基于 JavaEE 的 API(cmd /c python <args>
通过 ProcessBuilder)调用以下 Python 脚本,它访问 Excel 以导出一个table 到 PDF:
import sys
import win32com.client
import pathlib
if len(sys.argv) < 5:
print("Usage: %s input.xls output.pdf worksheet range" % sys.argv[0])
exit(1)
o = win32com.client.Dispatch("Excel.Application")
o.Visible = False
wb_path = r'C:\Develop\uploadedFile_5232859756803526399.xlsx'
path_to_pdf = sys.argv[2]
worksheet_idx = sys.argv[3]
print_area = sys.argv[4]
wb = o.Workbooks.Open(wb_path)
ws = wb.Worksheets[int(worksheet_idx)]
ws.Activate()
ws.PageSetup.Zoom = False
ws.PageSetup.FitToPagesTall = 1
ws.PageSetup.FitToPagesWide = 1
ws.PageSetup.PrintArea = print_area
wb.ActiveSheet.ExportAsFixedFormat(0, path_to_pdf)
wb.Close(True)
o.Quit()
wb_path = r'C:\Develop\uploadedFile_5232859756803526399.xlsx
仅用于 wb = o.Workbooks.Open(wb_path)
的测试目的(wb_path =sys.argv[1]
也不起作用),它会引发以下错误:
Traceback (most recent call last):
2022-01-13 14:46:24 INFO [utils.CMDUtils] File "C:\scripts\scriptWin.py", line 23, in <module>
2022-01-13 14:46:24 INFO [utils.CMDUtils] wb = o.Workbooks.Open(wb_path)
2022-01-13 14:46:24 INFO [utils.CMDUtils] File "<COMObject <unknown>>", line 5, in Open
2022-01-13 14:46:24 INFO [utils.CMDUtils] pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Microsoft Excel cannot access the file 'C:\Develop\uploadedFile_5232859756803526399.xlsx'. There are several possible reasons:\n\n• The file name or path does not exist.\n• The file is being used by another program.\n• The workbook you are trying to save has the same name as a currently open workbook.", 'xlmain11.chm', 0, -2146827284), None)
我做错了什么?当我在 Windows 2019 服务器上使用管理员直接在 CMD 中(通过远程桌面)调用此脚本时,它运行正常。
编辑
这是我的 Java 代码片段:
String catalinaBase = System.getProperty("catalina.base");
File logsFolder = new File(catalinaBase, "logs");
try(FileOutputStream fos = new FileOutputStream(new File(logsFolder,"cmd.log"));) {
List<String> python3 = new ArrayList<>();
if(OSUtils.isWindows()){
python3.add("cmd /c");
python3.add("python");
}else{
python3.add("python3");
}
python3.add(quoteStr(pythonScript.getAbsolutePath()));
if(params != null && params.size() > 0){
params.stream().forEach(p->{
python3.add(quoteStr(p));
});
}
ProcessBuilder pb = new ProcessBuilder(python3);
pb.redirectErrorStream(true);
Process process = OSUtils.isWindows() ?
Runtime.getRuntime().exec(String.join(" ", pb.command())) :
pb.start();
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", fos, log);
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", fos, log);
errorGobbler.start();
outputGobbler.start();
exitVal = process.waitFor(60, TimeUnit.SECONDS);
if(!exitVal){
errorGobbler.stopThread();
outputGobbler.stopThread();
process.destroyForcibly();
}
} catch (Exception e) {
e.printStackTrace();
}
StreamGobbler 与此类似:https://gist.github.com/jmartisk/6535784
设置问题。
打开DCOMCNFG,展开组件服务|我的电脑 | DCOM Config 并找到 Microsoft Excel Application -> Properties -> 在 Identity 选项卡下将其设置为“The interactive user”(仅限 RDP)或“This user”。用于后台服务。