Страницы: 1
RSS
Парсинг .txt: в таблицу из множества файлов получить последнюю строку.
 
Доброго дня! Подскажите, есть пачка TXT файлов, с которых необходима сводная таблица Excel в которой будут последние строчки этих файлов. Думал через Power Qwery собрать, но он тянет либо все с этих файлов либо ничего. поделитесь пожалуйста опытом, кто сталкивался с подобным?

PS как вариант, может это можно выдернуть через CMD или PowerShell, а потом закинуть в Excel....
Изменено: Filkri - 16.02.2022 09:55:08
 
Код
Option Explicit

Dim fso As Object

Sub GetLastRowsFromFiles()
    Dim fileList As Variant
    fileList = ShowFileDialog()
    If Not IsEmpty(fileList) Then
        Set fso = CreateObject("Scripting.FileSystemObject")
        Dim yTxt As Long
        Dim arrTxt As Variant
        ReDim arrTxt(1 To UBound(fileList), 1 To 1)
        Dim vFile As Variant
        For Each vFile In fileList
            yTxt = yTxt + 1
            arrTxt(yTxt, 1) = GetLastRow(vFile)
        Next
        
        OutPutTxt arrTxt
    End If
End Sub

Sub OutPutTxt(arr As Variant)
    With Workbooks.Add(1)
        With .Sheets(1).Cells(1, 1).Resize(UBound(arr, 1), UBound(arr, 2))
            .Value = arr
        End With
        .Saved = True
    End With
End Sub

Function GetLastRow(ByVal sFull As String) As String
    Dim txt As String
    Dim last As String
    
    With fso.OpenTextFile(sFull, 1)
        Do
            If .AtEndOfStream Then Exit Do
            txt = .ReadLine
            If txt <> "" Then last = txt
        Loop
        .Close
    End With
    GetLastRow = last
End Function

Function ShowFileDialog() As Variant

    Dim oFD As FileDialog
    Dim x, lf As Long
    'назначаем переменной ссылку на экземпляр диалога
    Set oFD = Application.FileDialog(msoFileDialogFilePicker)
    With oFD 'используем короткое обращение к объекту
    'так же можно без oFD
    'With Application.FileDialog(msoFileDialogFilePicker)
        .AllowMultiSelect = True
        .Title = "Выбрать файлы" 'заголовок окна диалога
        .Filters.Clear 'очищаем установленные ранее типы файлов
        '.Filters.Add "Excel files", "*.xls*;*.xla*", 1 'устанавливаем возможность выбора только файлов Excel
        .Filters.Add "Text files", "*.txt", 1 'добавляем возможность выбора текстовых файлов
        .Filters.Add "CSV files", "*.csv", 2 'добавляем возможность выбора текстовых файлов
        .FilterIndex = 1 'устанавливаем тип файлов по умолчанию - Text files(Текстовые файлы)
        .InitialFileName = ThisWorkbook.Path & "\"
        .InitialView = msoFileDialogViewDetails 'вид диалогового окна(доступно 9 вариантов)
        If oFD.Show = 0 Then Exit Function 'показывает диалог
        ReDim x(1 To .SelectedItems.Count)
        'цикл по коллекции выбранных в диалоге файлов
        For lf = 1 To .SelectedItems.Count
            x(lf) = .SelectedItems(lf) 'считываем полный путь к файлу
        Next
    End With
    ShowFileDialog = x
End Function
 
Цитата
Filkri написал: он тянет либо все с этих файлов либо ничего.
хотелось бы посмотреть на эти чудеса
 
Цитата
написал:
Думал через Power Qwery собрать
полагаю, можно что-то сделать - но надо видеть структуру. Есть же команда обратить строки. Применяем её и берем первую строку.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Написал как понял. Нужна только последняя непустая строка текстовых файлов.
Книга с макросом в той же папке, где текстовые файлы с расширением txt. Выгрузка на активный лист в 1 столбец.
Код
Sub enstaral11()
Dim File, Data$, Data1$, Put1$, Arr1, i&, Tp1
File = "*.txt": Put1 = ThisWorkbook.Path & "\": Data1 = "=FILES(""" & Put1 & File & """)"
Ima1 = "ZZZZ": ThisWorkbook.Names.Add Ima1, Data1, True
Tp1 = Evaluate(Ima1): ThisWorkbook.Names(Ima1).Delete
ReDim Arr1(1 To UBound(Tp1), 1 To 1)
For Each File In Tp1
Open Put1 & File For Input As #1: i = i + 1
    Do While Not EOF(1)
        Data1 = Space(Len(Data))
        Data1 = Data: Line Input #1, Data
    Loop
If Data = "" Then Arr1(i, 1) = Data1 Else Arr1(i, 1) = Data
Close #1
Next
Range("A1").Resize(UBound(Arr1)) = Arr1
End Sub
 
Цитата
Написал как понял.
Именно оно! Спасибо, но есть одно НО! данные дергаются через PowerShell и сохраняет в UTF-8... возможно работать с ней? ибо при загрузке русский текст выходит краказяброй =(

Цитата
Есть же команда обратить строки. Применяем её и берем первую строку.
Да простите, вы правы.... Смысл в чем есть скрипт на PowerShell который дергает пачку данных с пк, это имя пользователь серийник монитор и адрес компа,  данные разнятся ввиду колличества сетевых, мониторов и тд, необходимо собрать все в кучу одним файлом для анализа....

Цитата
хотелось бы посмотреть на эти чудеса
вообще изи, правда могут быть траблы из-за разности набора данных а так из файла - из папки - объединить, но он проглатывает весь текст, если не может переварить втыкает имя файла.
 
Filkri Если  кодировка UTF-8 попробуйте перед строкой Close #1 добавить строку. Правда не самое хорошее решение, но можно попробовать.
Код
Arr1(i, 1) = CreateObject("OlePrn.OleCvt.1").ToUnicode(Arr1(i, 1), 65001)
 
МатросНаЗебре,  очень интересно, спасибо, но мало чего понятно (мне) что куда и зачем...

Цитата
написал:Если  кодировка UTF-8 попробуйте перед строкой Close #1 добавить строку.
Спасибо, но результат тот же, скрипт переписывать на данный момент весьма проблемотично будет, потому выгоднее попробовать vbs заставить, когда начинаешь что-то строить всегда что-то вылазит...  вчера вечером уже не успел поковыряться щас попробую покрутить, может что и придумаю =)  
 
Цитата
Filkri написал:
Смысл в чем
прикрепите файл TXT. По скринам смысла нет что-то вообще пытаться сделать.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Простите тормознул... пожалуйста =) 3 документа примерного содержания. так +- может скакать наполняемость, но общая масса такая.  только таких документов 600+  
 
Текст запроса PQ:
Код
let
    txt = (filename as text) => let
        txt = Csv.Document(File.Contents(filename),2,"   ",ExtraValues.Ignore,1200),
        filterr = Table.SelectRows(txt, each ([Column1] <> "")),
        reverse_r = Table.FirstN(Table.ReverseRows(filterr),1)
    in
        reverse_r,

    Источник = Folder.Files("C:\TXT-файлы"),
    #"Другие удаленные столбцы" = Table.SelectColumns(Источник,{"Folder Path", "Name"}),
    #"Добавлен пользовательский объект" = Table.AddColumn(#"Другие удаленные столбцы", "TXT_LastRow", each txt([Folder Path]&[Name])),
    #"Развернутый элемент TXT_LastRow" = Table.ExpandTableColumn(#"Добавлен пользовательский объект", "TXT_LastRow", {"Column1", "Column2"}, {"Column1", "Column2"}),
    #"Удаленные столбцы" = Table.RemoveColumns(#"Развернутый элемент TXT_LastRow",{"Folder Path", "Name"})
in
    #"Удаленные столбцы"

вместо "C:\TXT-файлы" - путь к папке с Вашими текстовыми файлами. В качестве разделителя я взял три пробела, т.к. никакого другого вменяемого не нашел.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Дмитрий(The_Prist) Щербаков, приветствую! Думаю что реверс тут лишний есть же Table.LastN.
Такой вопрос: зачем собирать путь если есть готовые бинарники в столбце Content и можно с ними работать?
Вопрос не праздный, мы в тележном чате PBI регулярно отучаем граждан от такой практики ибо с динамическим путем в сервисе отчет не обновляется.
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
есть же Table.LastN
ну да. Изначально, без данных вариант с реверсом как пришел в голову, так его и использовал :)
Цитата
PooHkrd написал:
зачем собирать путь если есть готовые бинарники в столбце Content и можно с ними работать?
предполагалось, что человеку будет проще понять вариант с путями. А так-то без проблем:
Код
let
    txt = (filename as binary) => let
        txt = Csv.Document(Binary.From(filename),2,"   ",ExtraValues.Ignore,1200),
        filterr = Table.SelectRows(txt, each ([Column1] <> "")),
        reverse_r = Table.LastN(filterr,1)
    in
        reverse_r,

    Источник = Folder.Files("C:\TXT-файлы"),
    #"Другие удаленные столбцы" = Table.SelectColumns(Источник,{"Content"}),
    #"Добавлен пользовательский объект" = Table.AddColumn(#"Другие удаленные столбцы", "TXT_LastRow", each txt([Content])),
    #"Развернутый элемент TXT_LastRow" = Table.ExpandTableColumn(#"Добавлен пользовательский объект", "TXT_LastRow", {"Column1", "Column2"}, {"Column1", "Column2"}),
    #"Удаленные столбцы" = Table.RemoveColumns(#"Развернутый элемент TXT_LastRow",{"Content"})
in
    #"Удаленные столбцы"
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Текст запроса PQ:
Спасибо! Тогда решается вопрос со шрифтами, заодно и нашел пару косяков в файлах =)

Цитата
предполагалось, что человеку будет проще понять вариант с путями.
за это отдельное спасибо! с запросом пришлось малость погуглить, не сразу понял... но разобрался, с путями в принципе он и лучше будет =)

Цитата
В качестве разделителя я взял три пробела
разделители будут позже, там 2 строчки в код добавить, при этом структура и формат меняться не будет. об этом думал, но не было необходимости, причесывать все буду чутка позже =)

Подскажите пожалуйста, можно ли на данном этапе заставить разбивать его по пробелу, и разбить все по столбцам, их будет валом, но это пока, для новых данных надо время.
код более менее в курил, но увеличить количество столбцов, кроме как вручную накидать "Column1", "Column2"...... ничего не придумал.  

, ваш вариант тоже очень интересен, и понравился, попробую реализовать его тоже. нашел как изменить кодировку, но пока не могу прикрутить корректно....
Код
str.Charset = "UTF-8"
str.Open()
str.WriteText(Text)
str.SaveToFile "C:\UTF-8.txt", 2
str.Close()

думаю мож в 2 кнопки  пока сделать...  
 
Дмитрий(The_Prist) Щербаков, Покрутив поковыряв, получил такую табличку, Вообще супер! Спасибо! посмотрим как покажет себя со временем =) работает красиво.  
Изменено: Filkri - 17.02.2022 13:15:16
 
Дмитрий(The_Prist) Щербаков ,  Евгений Смирнов Спасибо Огромное мужики! Переспал с мыслью, и понял где я тормознул, переписал малость код и ушел от русских букв полностью, полернул выгрузку и и супер вообще! оба варианта работают как надо!

в PowerShell поменял формат даты и разобрался в чем затык был изначально (Get-Date -UFormat "%d/%m/%Y %R" )  добавил разделители, теперь все работает как часики разделение идет по * в 6 колонок.

Tot - logoff * 17/02/2022 17:54 * PC-42 * CAA404 * DELL SE2416H YBL * 1.1.1.1
Tot - logon * 18/02/2022 08:36 * PC-42 * CAA404 * DELL SE2416H YBL * 1.1.1.1  
Изменено: Filkri - 18.02.2022 07:59:24
Страницы: 1
Наверх