Spirtuoz 0 / 0 / 0 Регистрация: 31.01.2021 Сообщений: 1 |
||||
1 |
||||
Проверка, открыт ли Ворд31.01.2021, 22:25. Показов 3841. Ответов 4 Метки нет (Все метки)
Добрый день! Столкнулся с таким вопросом. Данный код открывает целевой документ Word
Однако, если данный документ уже открыт, макрос с данным кодом зависает. Как сделать, чтобы он проверял, открыт ли данный файл («Акт.docm») и: Надеюсь на вашу помощь.
0 |
4038 / 1423 / 394 Регистрация: 07.08.2013 Сообщений: 3,541 |
|
01.02.2021, 03:34 |
2 |
можно проверить наличие файла с именем
0 |
811 / 465 / 181 Регистрация: 09.03.2009 Сообщений: 1,577 |
|
01.02.2021, 11:29 |
3 |
snipe, этот файл может остаться от предыдущего вылета ворда, так что не показатель открытости и блокирования.
0 |
NewMaNew 5 / 5 / 0 Регистрация: 02.09.2020 Сообщений: 32 |
||||
01.02.2021, 12:25 |
4 |
|||
прошу прощения, не то ответил Добавлено через 10 минут
0 |
Alex77755 11482 / 3773 / 677 Регистрация: 13.02.2009 Сообщений: 11,145 |
||||
01.02.2021, 14:00 |
5 |
|||
Попадалась функция проверки открыт ли файл:
0 |
Группа: Пользователи Ранг: Прохожий Сообщений: 7
Замечаний: |
Добрый день! Столкнулся с таким вопросом.
Данный код открывает целевой документ Word
[vba]
Код
Set wd = New Word.Application
Set wdDoc = wd.Documents.Open _
(ThisWorkbook.Path & «» & «Акт.docm»)
wd.Visible = True
[/vba]
Однако, если данный документ уже открыт, макрос зависает. Как сделать, чтобы он проверял, открыт ли данный файл («Акт.docm») и
— если открыт, то переходил к следующему действию
— если закрыт то использовался код выше и переходил к следующему действию.
Надеюсь на вашу помощь.
You can enumerate all Word windows and try to find one with that document. Also if you try to open this file, while it’s opened in Word, you will get IOException. But it’s not perfect solution
Here is solution:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace WordExampleApp
{
class Program
{
const int ERROR_SHARING_VIOLATION = -2147024864;
static readonly string WORD_CLASS_NAME = "OpusApp";
static readonly string WORD_DOCUMENT_CLASS_NAME = "_WwB";
delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
static void Main(string[] args)
{
// Path to exist word document
string filePath = @"C:tempasdasd.docx";
string documentName = Path.GetFileNameWithoutExtension(filePath);
var isDocOpened = IsDocumentOpened(documentName);
Console.WriteLine("Is document opened: {0}", isDocOpened);
bool canRead = CanReadFile(filePath);
Console.WriteLine("Can read file: {0}", canRead);
}
private static bool CanReadFile(string path)
{
try {
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None)) { }
return true;
}
catch (IOException ex) {
if (ex.HResult == ERROR_SHARING_VIOLATION)
return false;
else throw;
}
}
private static bool IsDocumentOpened(string documentName)
{
IntPtr hwnd = FindWindow(WORD_CLASS_NAME, documentName + " - Word");
List<IntPtr> childs = GetChildWindows(hwnd);
var classText = new StringBuilder("", 1024);
var windowText = new StringBuilder("", 1024);
foreach (var childHwnd in childs)
{
if (0 == GetClassName(childHwnd, classText, 1024)) {
// something wrong
}
if (0 == GetWindowText(childHwnd, windowText, 1024)) {
// something wrong
}
var className = classText.ToString();
var windowName = windowText.ToString();
if (className == WORD_DOCUMENT_CLASS_NAME && windowName == documentName)
return true;
classText.Clear();
windowText.Clear();
}
return false;
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle gcHandle = GCHandle.Alloc(result);
try {
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(gcHandle));
}
finally {
if (gcHandle.IsAllocated)
gcHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
list.Add(handle);
return true;
}
[DllImport("user32", ExactSpelling = false, CharSet = CharSet.Auto)]
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
}
}
Sub Test()
Const DocFile$ = «D:123.doc»
Const MyDebug As Boolean = True ‘ Флаг отладки
‘ Проверить занятость файла
If IsOpen(DocFile) Then
MsgBox «Файл занят другим пользователем!», vbCritical, DocFile
Exit Sub
End If
Dim objWord As Object, IsNewApp As Boolean
‘ Попытаться использовать ранее открытое приложение WinWord (это быстрее)
On Error Resume Next
Set objWord = GetObject(, «Word.Application»)
If Err Then
‘ Открытое приложение WinWord не нвйдено — создать новое
Set objWord = CreateObject(«Word.Application»)
IsNewApp = True
End If
On Error GoTo exit_
‘ Открыть документ DocFile
With objWord
If MyDebug Then .Visible = True ‘<— для отладки
With .Documents.Open(DocFile)
‘ Что-то сделать с документом
.Content.Font.Name = «Arial»
‘ …
.Close True
End With
If IsNewApp Then .Quit
End With
exit_:
‘ Обязательно освободить память, занимаемую объектной переменной
Set objWord = Nothing
‘ При ошибке — сообщить
If Err Then MsgBox Err.Description, vbCritical, «Ошибка»
End Sub
Function IsOpen(File$) As Boolean
Dim FN%
FN = FreeFile
On Error Resume Next
Open File For Random Access Read Write Lock Read Write As #FN
Close #FN
IsOpen = Err
End Function
246
08 декабря 2005 года
GIZMO
1.8K / / 30.07.2004
Цитата:
Originally posted by richel
Как проверить, открыт ли документ Ворд? И если открыт, как осуществить прерывание обработки текста этого документа, по сути дела, отмену?
Желательно пример для OLE-сервера.
Ищу в интернете, намеков по этому вопросу не нахожу. Неужели это простой вопрос?:o
GetActiveOleObject позволит приконнектится к Word-у, у объекта Application есть св-во Documents, у того есть св-во Items и т.д.
Код:
Variant Word, Document;
Word = GetActiveOleObject(«Word.Application»);
Document = Word.Exec(PropertyGet(«Documents»)).Exec(Function(«Item») << «Документ1»);
Document.Exec(Function(«Close») << wdDoNotSaveChanges);
на второй строке или матюгнется или вернет NULL, проверишь сама…
wdDoNotSaveChanges — чему равно найдешь в хедере для TWordApplication он у меня не установлен.
Sub макрос()
Dim doc As Document
‘ Включение перехватчика run-ошибок, чтобы макрос продолжил работу при возникновении
‘ run-ошибки.
On Error Resume Next
‘ Присваиваем файлу имя «doc». Если файл не открыт, то в переменной «doc» будет Nothing.
Set doc = Documents(«C:UsersUserDesktopДокумент Microsoft Word.docx»)
‘ Отключение перехватчика ошибок, чтобы видеть непредвиденные ошибки.
On Error GoTo 0
‘ Проверка, открыт файл или нет.
If doc Is Nothing Then
MsgBox «Файл не открыт.», vbInformation
Else
MsgBox «Файл открыт.», vbInformation
End If
End Sub
[свернуть]
Вы можете перечислить все окна Word и попытаться найти их с этим документом. Также, если вы попытаетесь открыть этот файл, пока он откроется в Word, вы получите IOException. Но это не идеальное решение Вот решение:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace WordExampleApp
{
class Program
{
const int ERROR_SHARING_VIOLATION = -2147024864;
static readonly string WORD_CLASS_NAME = "OpusApp";
static readonly string WORD_DOCUMENT_CLASS_NAME = "_WwB";
delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
static void Main(string[] args)
{
// Path to exist word document
string filePath = @"C:tempasdasd.docx";
string documentName = Path.GetFileNameWithoutExtension(filePath);
var isDocOpened = IsDocumentOpened(documentName);
Console.WriteLine("Is document opened: {0}", isDocOpened);
bool canRead = CanReadFile(filePath);
Console.WriteLine("Can read file: {0}", canRead);
}
private static bool CanReadFile(string path)
{
try {
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None)) { }
return true;
}
catch (IOException ex) {
if (ex.HResult == ERROR_SHARING_VIOLATION)
return false;
else throw;
}
}
private static bool IsDocumentOpened(string documentName)
{
IntPtr hwnd = FindWindow(WORD_CLASS_NAME, documentName + " - Word");
List<IntPtr> childs = GetChildWindows(hwnd);
var classText = new StringBuilder("", 1024);
var windowText = new StringBuilder("", 1024);
foreach (var childHwnd in childs)
{
if (0 == GetClassName(childHwnd, classText, 1024)) {
// something wrong
}
if (0 == GetWindowText(childHwnd, windowText, 1024)) {
// something wrong
}
var className = classText.ToString();
var windowName = windowText.ToString();
if (className == WORD_DOCUMENT_CLASS_NAME && windowName == documentName)
return true;
classText.Clear();
windowText.Clear();
}
return false;
}
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle gcHandle = GCHandle.Alloc(result);
try {
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(gcHandle));
}
finally {
if (gcHandle.IsAllocated)
gcHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
list.Add(handle);
return true;
}
[DllImport("user32", ExactSpelling = false, CharSet = CharSet.Auto)]
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
}
}