Как отключить обновление экрана для другого приложения (блокнота)

Я написал макрос на vba, который открывает текстовый файл с помощью блокнота, выбирает весь текст и копирует его в Excel. Мне приходится обрабатывать таким образом около 100 файлов в день, и я хочу избавиться от мигающих изображений, которые я наблюдаю. Код работает, но проблема в том, что команда

Application.Screenupdating = False

Не работает с приложением блокнот. Я могу использовать только нормальный фокус, иначе код не работает. Как я могу выполнить приведенный ниже код, не замечая, что файл блокнота открыт и обработан?

Мой код:

Sub GetTextFile()
Application.ScreenUpdating = False
Dim MyPath As String
Dim MyFile As String

MyPath = "C:\Users\bgyona02\Desktop\OLAttachments\"

MyFile = Dir(MyPath & "*.txt", vbNormal)    

Do While Len(MyFile) > 0
  MyFile = Dir
Loop

Debug.Print GetTextFileContent(" C:\Users\bgyona02\Desktop\OLAttachments\" & MyFile)
    'MyFile = Shell("C:\WINDOWS\notepad.exe` C:\Users\bgyona02\Desktop\OLAttachments\" & MyFile, vbNormalFocus)
    'SendKeys "^a", True  '^A selects everything already in the pdf file.
    'SendKeys "^c", True
    'SendKeys "%fx", True
End Sub

Я не мог найти никакого рабочего решения по этому поводу.


person Badan    schedule 09.12.2016    source источник
comment
Когда я делаю что-то совершенно глупое, например, неправильно использую Блокнот и буфер обмена вместо того, чтобы делать что-то правильно, это вызывает проблемы. Может ли кто-нибудь сказать мне, как еще больше скрыть эти проблемы? известна как проблема XY. (Вам не нужно решать X, если вы изначально правильно решили Y.) Буфер обмена принадлежит пользователю, и вам не нужен Блокнот, чтобы открывать и читать текст из VBA.   -  person Ken White    schedule 10.12.2016


Ответы (2)


Есть быстрый ответ, как запустить Блокнот, но скрыть окно и использовать vbHide вместо vbNormalFocus в вашей команде Shell:

Dim strCmd = "C:\WINDOWS\notepad.exe C:\Users\bgyona02\Desktop\OLAttachments\" & LatestFile
MyFile = Shell(strCmd, vbHide)

Но я очень сомневаюсь, что SendKeys тогда работал бы с невидимым окном ....

Итак, это не ответ на вопрос, но рассматривали ли вы возможность использовать FileSystemObject и просто читать файл, фактически не открывая Notepad.exe?

Option Explicit

Const FOR_READING = 1

Sub LoadTextFile()
    Dim varTxtContent As Variant
    Dim intLine As Integer

    'Debug.Print GetTextFileContent("D:\temp.txt")

    varTxtContent = Split(GetTextFileContent("D:\temp.txt"), vbCr, -1, vbBinaryCompare)
    For intLine = 0 To UBound(varTxtContent) - 1
        ThisWorkbook.Worksheets("Sheet1").Range("B" & intLine + 1).Value = varTxtContent(intLine)
    Next intLine


End Sub

Function GetTextFileContent(strPath As String) As String
    Dim strContent As String
    Dim objFso As Object
    Dim objFile As Object
    Dim objStream As Object

    strContent = ""
    On Error GoTo CleanUp:

    Set objFso = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFso.GetFile(strPath)
    Set objStream = objFile.OpenAsTextStream(FOR_READING, 0)

    With objStream
        strContent = .ReadAll
        .Close
    End With

CleanUp:
    Set objStream = Nothing
    Set objFile = Nothing
    Set objFso = Nothing
    GetTextFileContent = strContent

End Function

Код будет работать с диакритическими символами, например. мой тестовый текстовый файл:

â, î or ô
foo
bar foo
baz bar foo

Насколько мне известно, Application.ScreenUpdating будет применяться только к вашему сеансу Excel, а не к другим программам, работающим в Windows. Итак, чтобы на самом деле прекратить появление этих окон - но по-прежнему иметь возможность читать содержимое окна - вам придется сделать что-то достаточно сложное с Windows API. Использование FileSystemObject намного проще.

HTH.

person Robin Mackenzie    schedule 09.12.2016
comment
Привет, Робин, спасибо за ответ. Я попытался открыть текстовый файл из Excel, но у меня проблема с акцентированными символами. Когда я открываю текстовый файл через блокнот, все символы отображаются правильно. Вот почему я ищу решение с редактором txt. - person Badan; 09.12.2016
comment
Можете ли вы привести пример текста, с которым вы работаете? - person Robin Mackenzie; 09.12.2016
comment
Я полагаю, функция Debug.Print должна копировать содержимое текстового файла ?. Я попытался добавить вашу функцию в свой код, но ничего не вышло. Пожалуйста, проверьте, я включил полный код в свой вопрос. Заранее спасибо! - person Badan; 09.12.2016
comment
Пожалуйста, добавьте образец текста к вашему вопросу. Текст в вашем файле европейского происхождения? Или русский, арабский или китайский? - person Robin Mackenzie; 09.12.2016
comment
Да, они могут быть на французском языке, поэтому у меня проблемы с символами é, но иногда мне также нужны символы â, î или ô, и они неправильно отображаются в Excel - person Badan; 09.12.2016
comment
Итак, в обновленном коде вы можете просто попробовать простой пример, в котором вы жестко запрограммировали имя файла, который хотите протестировать. Вам следует удалить код, который проверяет наличие \ в пути, а также тест на наличие последнего файла. Нам нужен минимальный и полный пример. - person Robin Mackenzie; 09.12.2016
comment
Можете ли вы вызвать незаметный блокнот и установить его размер 1x1 пиксель (или что-то достаточно маленькое, чтобы быть незаметным? - person B540Glenn; 09.12.2016
comment
Робин, сейчас я упростил код. Однако я не очень хорошо знаком с функцией отладочной печати. Как я могу использовать альтернативу ключам отправки, чтобы я мог копировать и вставлять данные? - person Badan; 09.12.2016
comment
B540Glenn, это можно сделать с помощью Excel, но я не уверен, можно ли это реализовать в Блокноте? - person Badan; 09.12.2016
comment
Я удалил использование Debug.Print (которое вы можете проверить в окне Immediate Window в редакторе VB) и заменил его кодом, который выводит на Sheet1 вашей книги, поэтому должно быть ясно, работает он для вас или нет. - person Robin Mackenzie; 10.12.2016
comment
Спасибо, Робин. К сожалению, мне не удалось получить эту работу. Однако я использовал альтернативный подход, предложенный B540Gleen. B540Glenn, огромное спасибо за эту идею, что вы дали мне поискать способ сделать экран в один пиксель. Тема теперь решена. Спасибо всем за сотрудничество. - person Badan; 12.12.2016

Наконец-то я нашел очень элегантное решение, которое может работать с внешними приложениями. Вся заслуга принадлежит Роберту Шутту, написавшему этот шедевральный код. Это делает окно блокнота 1 пикселем, поэтому мигающие изображения не наблюдаются. Мне это кажется довольно сложным, но это спасло меня:

Option Explicit

Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long

Public Const GW_HWNDNEXT As Long = 2
Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwprocessid As Long) As Long

Function ProcIDFromWnd(ByVal hwnd As Long) As Long
   Dim idProc As Long

   ' Get PID for this HWnd
   GetWindowThreadProcessId hwnd, idProc
   ProcIDFromWnd = idProc
End Function

Function GetWinHandle(hInstance As Long) As Long
   Dim tempHwnd As Long

   ' Grab the first window handle that Windows finds:
   tempHwnd = FindWindow(vbNullString, vbNullString)

   ' Loop until you find a match or there are no more window handles:
   Do Until tempHwnd = 0
      ' Check if no parent for this window
      If GetParent(tempHwnd) = 0 Then
         ' Check for PID match
         If hInstance = ProcIDFromWnd(tempHwnd) Then
            ' Return found handle
            GetWinHandle = tempHwnd
            ' Exit search loop
            Exit Do
         End If
      End If

      ' Get the next window handle
      tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
   Loop
End Function

Sub MinimizeNotepad()
    Dim retval As Long, np_retval As Long
    np_retval = Shell("C:\notepad.exe", vbNormalFocus)
    retval = MoveWindow(GetWinHandle(np_retval), 1, 1, 1, 1, 1) ' Application.hwnd
End Sub
person Badan    schedule 12.12.2016