DenSyo
Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору 5peciali5t тестовое решение в лоб на VBA Код: Function CaseFirstNonzero(ParamArray params() As Variant) As Long Dim i As Integer, k As Integer CaseFirstNonzero = -1 k = UBound(params(), 1) For i = 0 To k If CLng(params(i)) > 0 Then If CaseFirstNonzero = -1 Then CaseFirstNonzero = CLng(params(i)) Else If CaseFirstNonzero > CLng(params(i)) Then CaseFirstNonzero = CLng(params(i)) Next i End Function Function CaseMax(ParamArray params() As Variant) As Long Dim i As Integer, k As Integer CaseMax = -1 k = UBound(params(), 1) For i = 0 To k If CaseMax = -1 Then CaseMax = CLng(params(i)) Else If CaseMax < CLng(params(i)) Then CaseMax = CLng(params(i)) Next i End Function Function mspVersion(fileMask As String, Optional ByVal strDelim As String = "") As String Dim fso As Object, fileObj As Object Dim fileName As String, filePath As String, fileBuff As String, s As String Dim k As Long, kk As Long, n1 As Long, n2 As Long, n3 As Long, n4 As Long mspVersion = "" Set fso = CreateObject("Scripting.FileSystemObject") If strDelim = "" Then strDelim = Chr(13) & Chr(10) k = InStrRev(fileMask, "\") If k > 0 Then filePath = Left(fileMask, k) Else filePath = "" fileName = Dir(fileMask) Do While fileName <> "" mspVersion = mspVersion & "file: " & fileName & Chr(13) & Chr(10) Set fileObj = fso.OpenTextFile(filePath & fileName, 1, True, 0) On Error Resume Next fileBuff = fileObj.ReadAll fileObj.Close k = InStr(1, fileBuff, ".PatchCodePATCHNEWPACKAGECODEPATCHNEWSUMMARYSUBJECT") If k > 0 Then k = k + Len(".PatchCodePATCHNEWPACKAGECODEPATCHNEWSUMMARYSUBJECT") kk = InStr(k, fileBuff, "PATCHNEWSUMMARYCOMMENTS") If kk = 0 Then n1 = InStr(k, fileBuff, Chr(0)) n2 = InStr(k, fileBuff, Chr(1)) n3 = InStr(k, fileBuff, "_") n4 = InStr(k, fileBuff, "#") kk = CaseFirstNonzero(n1, n2, n3, n4) If kk > 0 Then mspVersion = mspVersion & "patch: " & Mid(fileBuff, k, kk - k) & Chr(13) & Chr(10) Else mspVersion = mspVersion & "patch: " & Mid(fileBuff, k, kk - k) & Chr(13) & Chr(10) k = kk + Len("PATCHNEWSUMMARYCOMMENTS") n1 = InStr(k, fileBuff, Chr(0)) n2 = InStr(k, fileBuff, Chr(1)) n3 = InStr(k, fileBuff, "_") n4 = InStr(k, fileBuff, "#") kk = CaseFirstNonzero(n1, n2, n3, n4) If kk > 0 Then mspVersion = mspVersion & "comments: " & Mid(fileBuff, k, kk - k) & Chr(13) & Chr(10) End If Else k = InStrRev(fileBuff, "Classification") kk = InStrRev(fileBuff, "DisplayName") If k > 0 And kk > 0 Then If kk > k Then k = k + Len("Classification") s = Mid(fileBuff, k, kk - k) n1 = InStr(1, s, Chr(0)) n2 = InStr(1, s, Chr(1)) n3 = InStr(1, s, "@") n4 = InStr(1, s, "#") k = CaseFirstNonzero(n1, n2, n3, n4) If k > 0 Then s = Left(s, k - 1) mspVersion = mspVersion & "patch: " & s & Chr(13) & Chr(10) k = kk + Len("DisplayName") kk = InStr(k, fileBuff, "Description") If kk - k > 0 Then mspVersion = mspVersion & "description: " & Mid(fileBuff, k, kk - k) & Chr(13) & Chr(10) Else kk = kk + Len("DisplayName") s = Mid(fileBuff, kk, k - kk) n1 = InStrRev(s, Chr(0)) n2 = InStrRev(s, Chr(1)) n3 = InStrRev(s, "@") n4 = InStrRev(s, "#") k = CaseMax(n1, n2, n3, n4) If k > 0 Then s = Right(s, Len(s) - k) mspVersion = mspVersion & "patch: " & s & Chr(13) & Chr(10) kk = kk - Len("DisplayName") k = InStrRev(fileBuff, "Description", kk) If k > 0 Then k = k + Len("Description") If kk - k > 0 Then mspVersion = mspVersion & "description: " & Mid(fileBuff, k, kk - k) & Chr(13) & Chr(10) End If End If Else End If End If fileName = Dir() If fileName <> "" Then mspVersion = mspVersion & strDelim Loop End Function | парсинг уже отрабатывает нормально большую часть патчей, по мере тестов допилится. слабое место - чтение файлов. файл читается целиком в переменную, что очень медленно на больших файлах. надо искать решение быстрого поиска вхождения строки в файле и читать небольшой фрагмент. для тестирования создайте документ эксель, запустите VBA, создайте модуль и вставьте в него приведенный код. в любой ячейке вставьте функцию: =mspVersion("c:\Windows\Installer\*.msp") только для начала укажите один любой файл вместо маски *, иначе это надолго) по умолчанию разделитель списка chr(13) & chr(10), для разбития строки в массив используйте другой разделитель который бы не встречался в возвращаемом тексте, например: chr(8) & chr(8) или любая абракадабра. ps заменил стандартное чтение файлов на метод FileSystemObject, это дает приемлемую скорость чтения. теперь идея с парсингом вполне жизнеспособна, тем более что система не всегда показывает в свойствах полную информацию. | Всего записей: 219 | Зарегистр. 19-01-2008 | Отправлено: 10:18 03-04-2018 | Исправлено: DenSyo, 14:22 03-04-2018 |
|