Что нового

По нажатию кнопки копировать экселевский файл в папку, включив мониторинг, переименовать и отослать на почту

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
Доброго времени суток. Решил написать в стол заказов, потому что сам не могу осилить, а в обычной теме пока никто не стал разбираться. При этом время стало поджимать.
Сперва то, что нужно получить. В окошке выбирается файл эксель. По нажатии кнопки "Старт" он копируется в дефолтную папку (@ScriptDir & '\~TEST~'). При этом включается мониторинг за этой папкой. Мониторинг осуществляется с помощью UDF RDC от Yashied. Функция Exel() сохраняет файл с новым именем в (@DesktopDir & "\Отчеты\" & "new.xlsx"). После этого переименованный файл отправляется по почте. и мониторинг за папкой прекращается (возможно на предыдущем шаге, сразу после запуска переименования файла). И после этого по желанию окошко либо закрывается, либо выбирается новый файл, который опять копируется, переименовывается и отсылается по почте.
Из того, что у меня получается: Если папку не мониторить (закоментировать функцию мониторинга), то могу настроить переименование и отправку почты (потому что знаю, как называется выбранный файл). Но все дело в том, что это только часть скрипта. В полном я не сам копирую файл, поэтому и нужно мониторить папку. В полном стороння программа закидывает нужный файл и с ним необходимо произвести манипуляции, переименовать и отправить по почте. Эта стороння программа закидывает много разных файлов. Я могу лишь инициировать закидывание нужного мне, но не знаю как он будет называться. Для этого нужно включать мониторинг на тот промежуток, пока закидывается). Если же включить мониторинг, то файл "отлавливается" и может даже переименоваться, но почта не отправляется и не возможно закрыть окошко, нажать хоть на какую-то кнопку. Пробовал отменить мониторинг. Вроде отменяется, но окошко все равно висит и с ним ничего нельзя сделать. При этом ради эксперимента закидывал файл не через окошко и мониторинг уже не реагирует, а окошко продолжает "висеть".
Ниже код с посильными пояснениями.
Код:
#include <Array.au3>
#Include <APIConstants.au3>
#include <APIFilesConstants.au3>
#include <AutoItConstants.au3>
#include <Constants.au3>
#include <Date.au3>
#include <Excel.au3>
#include <File.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GUIDateTimePicker.au3>
#Include <RDC.au3>
#include <String.au3>
#include <WinAPI.au3>
#include <WinAPIProc.au3>
#include <WinAPIError.au3>
#include <WinAPIFiles.au3>
#include <WinAPIMem.au3>
#include <WindowsConstants.au3>

#RequireAdmin

#pragma compile(AutoItExecuteAllowed, True)
HotKeySet('{ESC}','_out');клавиша выхода - Esc

Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)

Global $sValidFName_Pattern = '^(?!~\$).*?\.xlsx$'
Global $sRenamed_FName = ''

Global $hWnd = GUICreate('')
Global $sEvents = ''
Global $stat, $Otchet

;Папка куда копируется выбранный файл и для которой включается мониторинг
Global Const $sDir = @ScriptDir & '\~TEST~'

Global $hGui = GUICreate('Окно копирования', 700, 680, -1, -1, -1, $WS_EX_TOPMOST)
Local $btStart = GUICtrlCreateButton('Старт', 392, 8, 75, 25)
Local $sPathSS = GUICtrlCreateInput('', 8, 96, 325, 21)
Local $sPathS = GUICtrlCreateButton('Откуда', 392, 96, 75, 25)
Local $btClear = GUICtrlCreateButton('Очистить', 392, 630, 75, 25)


GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE

           ; ProcessClose($iPid)
            Exit
        Case $sPathS
            GUICtrlSetData($sPathSS, '')
            Local $sPS = FileOpenDialog('Выбор копируемого файла', '', "(*.xlsx)")
            If Not @error Then GUICtrlSetData($sPathSS, $sPS)
        Case $btStart

            _Copy()
            _Excel($sPS)  ; Если раскомментировать эту строку и закоментировать строку ниже, то все работает и письмо отправляется
        ;_Dir()  ; Если эта строка раскомментирована, то включается слежение за каталогом, но все остальное не работает.
            Sleep(3000)
            _Mail($Path, $Subject)

        Case $btClear
            GUICtrlSetData($sPathSS, '')
            _Clear()
   EndSwitch
WEnd

Func _Copy()
   FileDelete('copy.txt')
   If FileExists($sPS) Then ;And FileExists($sPD) Then
      FileWrite('copy.txt', "$Shell = ObjCreate('Shell.Application')" & @CRLF & "$Shell.NameSpace('" & $sDir & "').CopyHere('" & $sPS & "', 16)")
    Local $iPid = Run(@AutoItExe & ' /AutoIt3ExecuteScript copy.txt')
   EndIf

EndFunc

  Func _Clear()
Local $aRS = IniReadSection("Setting.ini", "Путь")
If Not @error Then
    For $i = 1 To $aRS[0][0]
        $aRS[$i][1] = ''
    Next
    IniWriteSection("Setting.ini", "Путь", $aRS)
EndIf
Local $LCC = IniReadSection("Setting.ini","Statistika")
If Not @error Then
    For $j = 1 To $LCC[0][0]
        $LCC[$j][1] = ''
    IniWrite("Setting.ini","Statistika", $LCC[$j][0], '')
    Next
EndIf
Local $IMG = IniReadSection("Setting.ini","ПутьСкрин")
If Not @error Then
    For $k = 1 To $IMG[0][0]
        $IMG[$k][1] = ''
    FileDelete(IniRead("Setting.ini","ПутьСкрин", $IMG[$k][0], ''))
    IniWrite("Setting.ini","ПутьСкрин", $IMG[$k][0], '')
    Next
EndIf
EndFunc

Func _Excel($Otchet)
    ConsoleWrite('Из РДЦ   :' & $sDir & @CR)
Local $g_sPath=$sDir
Local $Otchet1 = _StringExplode($Otchet, '\')
Local $Otchet2 = $Otchet1[UBound($Otchet1)-1]
ConsoleWrite('новый эксель1  ' & '\' & $Otchet2 & @CR)
    Local $oExcel = _Excel_Open()
    Local $sWorkbook = $g_sPath  & '\' & $Otchet2
    ConsoleWrite('новый эксель2  ' & $sWorkbook & @CR)
    Local $oWorkbook = _Excel_BookOpen($oExcel,$sWorkbook)
    If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_BookOpen Example 1", "Error opening '" & $sWorkbook & "'." & @CRLF & "@error = " & @error & ", @extended = " & @extended)
;MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_BookOpen Example 1", "Workbook '" & $sWorkbook & "' has been opened successfully." & @CRLF & @CRLF & "Creation Date: " & $oWorkbook.BuiltinDocumentProperties("Creation Date").Value)
Local $Otchet4 = @DesktopDir & "\Отчеты\" & $Otchet2
ConsoleWrite('перед сохранением  ' & $Otchet4 & @CR)
$sWorkbook = @DesktopDir & "\Отчеты\" & "new.xlsx"
ConsoleWrite('по идее сохранение  ' & $sWorkbook & @CR)
_Excel_BookSaveAs($oWorkbook, $sWorkbook, $xlWorkbookDefault, True)

    ; Закрытие экселя
    _Excel_BookClose($oWorkbook, False)
    _Excel_Close($oExcel, False, True)
    Global $Path = $sWorkbook
    Global $Subject = "Отчет за  " & _Now()

EndFunc


Func _Mail($Path, $Subject)
   ConsoleWrite('Отправка почты  ' & @CR)
   Local $str = "http://schemas.microsoft.com/cdo/configuration/"

   Local $hMAIL = ObjCreate ("CDO.Message")
    With $hMAIL
        .From = "****@gmail.com";
        .To = "****@ukr.net"
        .Subject = $Subject
        .TextBody = "Письмо отправлено от " & _Now()
       .AddAttachment ($Path)  ;файл для отправки
    EndWith
    With $hMAIL.Configuration.Fields
        .Item ($str & "sendusing") = 2
        .Item ($str & "smtpserver") = "smtp.gmail.com" ;SMTP Server
        .Item ($str & "smtpusessl") = True
        .Item ($str & "smtpauthenticate") = 1
        .Item ($str & "sendusername") = "****@gmail.com"
        .Item ($str & "sendpassword") = "****" ;Пароль SMTP-сервер
        .Item ($str & "smtpserverport") = 465        ;Порт
        .Update
    EndWith
$hMAIL.Send
If Not @error Then
   MsgBox($MB_SYSTEMMODAL, "",  $Subject & " создан , почта отправлена", 0, $hGUI)
Else
   MsgBox($MB_SYSTEMMODAL, "",  $Subject & " создан ,но почта не отправлена", 0, $hGUI)
EndIf
EndFunc


Func _Dir()
   _RDC_OpenDll()
If @Error Then
    ConsoleWrite('Error: _RDC_OpenDll() - ' & @Error & @CR)
    Exit
EndIf

Global $hWnd = GUICreate('')
Global $sEvents = ''

If Not FileExists($sDir) Then
    DirCreate($sDir)
EndIf

GUIRegisterMsg($WM_RDC, 'WM_RDC')

_RDC_Create($sDir, 1, BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME, $FILE_NOTIFY_CHANGE_SIZE), 0, $hWnd)
If @Error Then
    ConsoleWrite('Error: _RDC_Create() - ' & @Error & ', ' & @Extended & @CR)
    Exit
EndIf

While 1
    Sleep(1000)
WEnd

EndFunc

Func WM_RDC($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    Local $aData = _RDC_GetData($lParam)

    If @Error Then

        ; Do something because notifications will not come from this thread!
        ConsoleWrite('Error: _RDC_GetData() - ' & @Error & ', ' & @Extended & ', ' & _RDC_GetDirectory($lParam) & @CR)

        _RDC_Delete($lParam)
        Return 0
    EndIf
    For $i = 1 To $aData[0][0]
        If $sEvents Then
            $sEvents &= '|'
        EndIf
        $sEvents &= $aData[$i][1] & '?' & _RDC_GetDirectory($lParam) & '\' & $aData[$i][0]
    Next
    AdlibRegister('_RetrieveDirectoryChanges', 250)
    Return 0

EndFunc   ;==>WM_RDC


Func _RetrieveDirectoryChanges()
ConsoleWrite("следим за $sDir" & $sDir & @CR)
    AdlibUnRegister('_RetrieveDirectoryChanges')

;    ConsoleWrite('для закрытия1  ' & $iID & @CR)
    Local $aData, $aText, $aPrev[2] = [0, ''], $sPrev = ''

    $aData = StringSplit($sEvents, '|', 2)
    $sEvents = ''
    If Not IsArray($aData) Then
        Return
    EndIf
    For $i = 0 To UBound($aData)
        If $i < UBound($aData) Then
            If $aData[$i] = $sPrev Then
                ContinueLoop
            EndIf
            $sPrev = $aData[$i]
            $aText = StringSplit($aData[$i], '?', 2)
            If IsArray($aText) Then
;~                ConsoleWrite($aText[0] & ' - ' & $aText[1] & @CR)
;~                ContinueLoop
                Switch Number($aText[0])
                    Case 1 ; FILE_ACTION_ADDED
                        Switch Number($aPrev[0])
                            Case 2
                                If StringRegExpReplace($aPrev[1], '^.*\\', '') = StringRegExpReplace($aText[1], '^.*\\', '') Then
                                    If $aPrev[1] = $aText[1] Then
;~                                        If _IsDirectory($aText[1]) Then
;~                                            ; Nothing
;~                                        Else
;~                                            ; Nothing
;~                                        EndIf
                                        $aPrev[0] = 0
                                        ContinueLoop
                                    Else
                                        If _IsDirectory($aText[1]) Then
                                            ConsoleWrite('DIRECTORY MOVED1: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
                                        Else
                                            ConsoleWrite('FILE MOVED1: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
                                        EndIf
                                        $aPrev[0] = 0
                                        ContinueLoop
                                    EndIf
                                EndIf
                        EndSwitch
                    Case 2 ; FILE_ACTION_REMOVED
                        ; Nothing
                    Case 3 ; FILE_ACTION_MODIFIED
                        Switch Number($aPrev[0])
                            Case 1
;~                                If True Then
                                    If $aPrev[1] = $aText[1] Then
                                        If _IsDirectory($aText[1]) Then
                                            ; Nothing
                                        Else
                                              Local $PathM = StringSplit($aText[1], '\')
                                             Local $PathMA[0]
                                             _ArrayAdd($PathMA, $PathM)
                                             ;_ArrayDisplay($PathMA)
                                             Local $maxIn = UBound($PathMA)-1
                                             ConsoleWrite('Путь   ' & $PathMA[$maxIn] & @CR)

    ;Ничего не делаем если: файл не существует, не является валидным эксель файлом, или это наш переименованный файл
    If Not StringRegExp($PathMA[$maxIn], $sValidFName_Pattern) Or $PathMA[$maxIn] = $sRenamed_FName Then
        Return
     Else
        ConsoleWrite('появился файл  ' & $PathMA[$maxIn] & @CR)
        _Excel($PathMA[$maxIn])
;   _LV_Delete($sDir)  ; Если раскомментировать, то до прекращения слежения за каталогом не доходит
;   _RDC_Destroy()  ;
     EndIf
;    ContinueLoop

                                        EndIf
                                        $aPrev[0] = 0
                                        ContinueLoop
                                    EndIf
;~                                EndIf
                            Case 2
                                If StringRegExpReplace($aPrev[1], '^.*\\', '') = StringRegExpReplace($aText[1], '^.*\\', '') Then
;~                                    If True Then
                                        If _IsDirectory($aText[1]) Then
                                            ; Nothing
                                        Else
                                            ConsoleWrite('FILE DELETED1: ' & $aText[1] & @CR)
                                            ConsoleWrite('FILE MOVED2: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
                                        EndIf
                                        $aPrev[0] = 0
                                        ContinueLoop
;~                                    EndIf
                                EndIf
                        EndSwitch
                    Case 4 ; FILE_ACTION_RENAMED_OLD_NAME
                        ; Nothing
                    Case 5 ; FILE_ACTION_RENAMED_NEW_NAME
                        Switch Number($aPrev[0])
                            Case 4
                                If StringRegExpReplace($aPrev[1], '\\[^\\]*\Z', '') = StringRegExpReplace($aText[1], '\\[^\\]*\Z', '') Then
;~                                    If True Then
                                        If _IsDirectory($aText[1]) Then
                                            ConsoleWrite('DIRECTORY RENAMED1: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
                                        Else
                                            ConsoleWrite('FILE RENAMED1: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
                                        EndIf
                                        $aPrev[0] = 0
                                        ContinueLoop
;~                                    EndIf
                                EndIf
                        EndSwitch
                EndSwitch
            EndIf
        EndIf
        Switch Number($aPrev[0])
            Case 1 ; FILE_ACTION_ADDED
                If _IsDirectory($aPrev[1]) Then
                    ConsoleWrite('DIRECTORY ADDED2: ' & $aPrev[1] & @CR)
                Else
                    ConsoleWrite('FILE ADDED2: ' & $aPrev[1] & @CR)
                EndIf
            Case 2 ; FILE_ACTION_REMOVED
;~                If True Then
                    ConsoleWrite('FILE OR DIRECTORY DELETED3: ' & $aPrev[1] & @CR)
                    ConsoleWrite('FILE OR DIRECTORY DELETED3: ' & StringRegExpReplace($aPrev[1], '\\[^\\]*\Z', '\') & @CR)
;~                EndIf
            Case 3 ; FILE_ACTION_MODIFIED
                If _IsDirectory($aPrev[1]) Then
                    ; Nothing
                Else
                    ConsoleWrite('FILE MODIFIED4: ' & $aPrev[1] & @CR)
                EndIf
        EndSwitch
        $aPrev = $aText
    Next
    ConsoleWrite('---------------------------------------------' & @CR)

   _LV_Delete($sDir)  ; Если раскомментировать, то перестает следить за каталогом, но все остальное не работает
   _RDC_Destroy()

EndFunc   ;==>_RetrieveDirectoryChanges

Func _IsDirectory($sPath)
    If StringInStr(FileGetAttrib($sPath), 'D') Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc   ;==>_IsDirectory

Func _LV_Delete($sDir)

    If _RDC_Delete($sDir) Then
        If _RDC_Delete($sDir) Then
            _WinAPI_KillTimer(0, 1)
        EndIf
    EndIf

EndFunc   ;==>_LV_Delete

;Функция для закрытия процесса аутоит, слежения за папкой.
Func _out()
Local $aData = _WinAPI_EnumChildProcess(_WinAPI_GetParentProcess())
;_ArrayDisplay($aData, '_WinAPI_EnumChildProcess')
ProcessClose($aData[1][0])
EndFunc
Версия SciTE-Lite Version 3.5.4
 
Последнее редактирование:
Верх