我有数千个docx文件,我需要通过python提取其中的某些元素。我在Python脚本中使用win32com.client完成此任务。
def checkinc(inputstring, straightlength):
for startdigit in range(len(inputstring)-straightlength+1):
for i in range(straightlength):
if int(inputstring[startdigit+i]) != (int(inputstring[startdigit]) + i)%10:
return False
return True
这对于99%的文件都适用;但是,对于几个文件,将启动Microsoft Word对话框:“ 作者希望您以只读方式打开它,除非您需要进行更改。以只读方式打开?”。此时脚本停止,等待用户输入。
在对话框上按是继续运行脚本;但是,这是不合格的,因为我需要它完全自动化,而不会出现任何对话框。有什么方法可以通过win32com Python或通过MS Word永久禁用MS Word提示符吗? (注意:在这里,不能将import docx替换为win32com。)
答案 0 :(得分:0)
Office应用程序是最终用户应用程序,并未作为开发工具进行优化。这意味着它们在等待用户输入时似乎挂起,如问题中所述。没有简单,干净的方法可以解决此问题,这就是为什么建议在需要关闭对话框的情况下利用Open XML文件格式的原因...
如果必须使用自动化,那么我知道有两种可能性。详细信息不是python,但这确实记录了基本方法。
本节中的步骤演示了Microsoft Word的自动化 打印文档。自动化客户端调用PrintOut方法用于 Word文档对象。如果配置了用户的默认打印机 打印到FILE端口,然后调用PrintOut会产生一个对话框 提示用户输入文件名的框。确定是否 PrintOut方法使此对话框出现,Visual Basic 自动化客户端使用Timer控件来检测之后的空闲时间 调用PrintOut方法。在调用PrintOut之前,计时器是 启用并设置为在五秒钟内触发。当PrintOut完成时, 计时器已禁用。因此,如果PrintOut方法在 五秒钟,Timer事件永远不会发生,并且没有进一步的操作 采取。打印文档,代码执行继续 PrintOut方法。但是,如果Timer事件在 五秒钟的间隔,假定PrintOut方法没有 已完成,并且延迟是由对话框等待引起的 用户输入。发生Timer事件时,自动化客户端会提供 将焦点放在Word上,并使用SendKeys关闭对话框。
注意出于演示目的,此示例使用PrintOut方法 以某种方式在它有意显示对话框时 打印到设置为FILE端口的打印机。请注意,PrintOut 方法具有两个参数,OutputfileName和PrintToFile,您可以 提供以避免出现此对话框。
此外,在使用这种“计时器”方法时,您可以自定义 等待时间大于或小于5秒,以及 自定义发送到对话框的击键。
此演示包含两个Visual Basic项目:
提供用于检测延迟的Timer类的ActiveX EXE。将ActiveX EXE用于Timer类的原因是在单独的进程(因此,在单独的线程)中运行Timer代码。 这使得Timer类可以在 暂停的自动化呼叫。
一个标准EXE,它使用Word的自动化功能,并调用PrintOut方法来打印文档。它使用ActiveX EXE来检测延迟 调用PrintOut方法时。创建ActiveX EXE项目
- 启动Visual Basic并创建一个ActiveX EXE项目。默认情况下创建Class1。
- 在“项目”菜单上,单击以选择“属性”,然后将“项目”名称更改为MyTimer。
- 将以下代码复制并粘贴到Class1模块中:Option Explicit
Public Event Timer() Private oForm1 As Form1
Private Sub Class_Initialize()
Set oForm1 = New Form1
oForm1.Timer1.Enabled = False
End Sub
Private Sub Class_Terminate()
Me.Enabled = False
Unload oForm1
Set oForm1 = Nothing
End Sub
Public Property Get Enabled() As Boolean
Enabled = oForm1.Timer1.Enabled
End Property
Public Property Let Enabled(ByVal vNewValue As Boolean)
oForm1.Timer1.Enabled = vNewValue
If vNewValue = True Then
Set oForm1.oClass1 = Me
Else
Set oForm1.oClass1 = Nothing
End If
End Property
Public Property Get Interval() As Integer
Interval = oForm1.Timer1.Interval
End Property
Public Property Let Interval(ByVal vNewValue As Integer)
oForm1.Timer1.Interval = vNewValue End Property
Friend Sub TimerEvent()
RaiseEvent Timer
End Sub
- 在“项目”菜单上,选择“添加表单”以将新表单添加到项目中。
- 将Timer控件添加到窗体。
- 将以下代码复制并粘贴到Form1:Option Explicit的代码模块中
Public oClass1 As Class1
Private Sub Timer1_Timer()
oClass1.TimerEvent
End Sub
- 将此项目保存在名为Server的新子文件夹中。
- 在“文件”菜单上,选择“制作MyTimer.Exe”以生成并注册该组件。创建自动化客户端
yet
:这里是一个示例,该示例通过C#中的pinvoke使用Win32 API。我是 能够处理已知的Word窗口,例如Word-> File-> Options对话框 窗口通过FindWindow和SendMessage或PostMessage。请离开 通过示例,看看它是否对您有用。自从你 知道要丢弃的对话框,请使用spy ++ 找到窗口标题和窗口类,并在此示例中使用它。
对于您的情况,可能不需要SendKeys。
希望这会有所帮助。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SendKeys
{
public partial class Form1 : Form
{
// For Windows Mobile, replace user32.dll with coredll.dll
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// the caption and the className is for the Word -> File -> Options window
// the caption and the className are got by using spy++ application and focussing on the window we are researching.
string caption = "Word Options";
string className = "NUIDialog";
IntPtr hWnd= (IntPtr)(0);
// Win 32 API being called through PInvoke
hWnd = FindWindow(className, caption);
/*bool retVal = false;
if ((int)hWnd != 0)
{
// Win 32 API being called through PInvoke
retVal = SetForegroundWindow(hWnd);
}*/
if ((int)hWnd != 0)
{
CloseWindow2(hWnd);
//CloseWindow(hWnd); // either sendMessage or PostMessage can be used.
}
}
static bool CloseWindow(IntPtr hWnd)
{
// Win 32 API being called through PInvoke
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
return true;
}
static bool CloseWindow2(IntPtr hWnd)
{
// Win 32 API being called through PInvoke
PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
return true;
}
}
}