![](/img/trans.png)
[英]Python pywin32 (win32com.client) responses wrong table before Microsoft Word document ready after open()
[英]Cannot open read-only Microsoft Word files with win32com.client
我有數千個docx文件,我需要通過python提取其中的某些元素。 我在Python腳本中使用win32com.client完成此任務。
import win32com.client
doc = win32com.client.GetObject(some_path_to_a_docx_file)
這對於99%的文件都可以正常工作; 但是,對於一些文件,將啟動Microsoft Word對話框:“ 作者希望您以只讀方式打開它,除非您需要進行更改。以只讀方式打開? ”。 此時腳本停止,等待用戶輸入。
在對話框上按是繼續運行腳本; 但是,這是不合格的,因為我需要它完全自動化,而不會出現任何對話框。 有什么方法可以通過win32com Python或通過MS Word永久禁用MS Word提示符嗎? (注意:在這里,不能將import docx替換為win32com。)
Office應用程序是最終用戶應用程序,並未作為開發工具進行優化。 這意味着它們在等待用戶輸入時似乎掛起,如問題中所述。 沒有簡單,干凈的方法可以解決這個問題,這就是為什么建議在需要關閉對話框的情況下利用Open XML文件格式的原因...
如果必須使用自動化,那么我知道有兩種可能性。 詳細信息不是python,但這確實記錄了基本方法。
本節中的步驟演示了Microsoft Word的自動化以打印文檔。 自動化客戶端調用Word Document對象的PrintOut方法。 如果將用戶的默認打印機配置為打印到FILE端口,則對PrintOut的調用將產生一個對話框,提示用戶輸入文件名。 若要確定PrintOut方法是否導致此對話框出現,Visual Basic Automation客戶端使用Timer控件在調用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方法來打印文檔。 調用PrintOut方法時,它使用ActiveX EXE來檢測延遲。 創建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
- 在項目菜單上,選擇添加表單以將新表單添加到項目。
- 將計時器控件添加到窗體。
- 將以下代碼復制並粘貼到Form1的代碼模塊中:Option Explicit
Public oClass1 As Class1
Private Sub Timer1_Timer()
oClass1.TimerEvent
End Sub
- 將此項目保存在一個名為Server的新子文件夾中。
- 在“文件”菜單上,選擇“制作MyTimer.Exe”以生成並注冊該組件。 創建自動化客戶端
yet
: 這是通過C#中的pinvoke使用Win32 API的示例。 我可以通過FindWindow和SendMessage或PostMessage處理已知的Word窗口,例如Word-> File-> Options對話框窗口。 請仔細閱讀示例,看看它是否對您有用。 由於您知道要丟棄的對話框,因此請使用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;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.