1 (изменено: Rabi, 2020-06-25 08:45:57)

Тема: VBS: для объединения CSV файлов

Здравствуйте! Столкнулся со следующей проблемой, у нас есть 108 расходомерных устройств которые регулярно отправляют отчет в виде "CSV" файлов с датами на хвосте (MAG8000_296305H319_2020-02-08 0403, MAG8000_296305H319_2020-02-26 0701).Для того чтоб каждый файл с определенной датой не открывать отдельно. Можно ли их объединять в один архивный CSV файл например: MAG8000_296305H319.csv где собраны записи за весь период. При этом надо чтоб скрипт делал запись нового файла в архивный файл однократно, во избежания дублированных записей при каждом вызове скрипта.

2 (изменено: Rumata, 2020-06-25 08:53:41)

Re: VBS: для объединения CSV файлов

Можно. Но лучше это сделать через батник:


@echo off

if "%~1" == "" (
	echo:Usage: %~n0 date
	goto :EOF
)

setlocal

set "SRC_DATE=%~1"
set "SRC_TMPL=MAG8000_*_%SRC_DATE%"
set "DST_FILE=MAG8000_%SRC_DATE%.csv"

type nul > "%DST_FILE%"

for /f "tokens=*" %%f in ( 'dir /b /s /a-d "%SRC_TMPL%"' ) do type "%%f" >> "%DST_FILE%"

Скрипт вызывается с обязательным параметром - дата (например, 2020-02-26).
Скрипт рекурсивно ищет в текущей директории все файлы согласно формату MAG8000_*_дата и собирает их все в файл по имени MAG8000_дата.csv.

Вас самому надо определить точно:
-- шаблон для поиска оригинальных файлов
-- имя для результирующего файла

( 2 * b ) || ! ( 2 * b )

3 (изменено: wisgest, 2020-06-25 09:29:54)

Re: VBS: для объединения CSV файлов

Rumata, а почему

type nul > "%DST_FILE%"

for /f "tokens=*" %%f in ( 'dir /b /s /a-d "%SRC_TMPL%"' ) do type "%%f" >> "%DST_FILE%"

а не

(for /f "tokens=*" %%f in ( 'dir /b /s /a-d "%SRC_TMPL%"' ) do type "%%f") > "%DST_FILE%"

— есть какие-то преимущества или просто дело вкуса?
Ну и

Rabi пишет:

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

— вероятно, надо сбрасывать атрибут «Архивный» и не обрабатывать файлы без этого атрибута или как-то ещё.

4 (изменено: Rumata, 2020-06-25 10:52:35)

Re: VBS: для объединения CSV файлов

wisgest пишет:

а почему

Потому что не догадался о таком варианте. (-:

wisgest пишет:

Ну и

Добавить проверку перед созданием файла и прекращать выполнение скрипта если файл существует и выставлен атрибут. Но я считаю, что это избыточно. Достаточно пересоздавать файл на заданную дату при каждом запуске скрипта. Что и делает предложенный скрипт (оригинальный мой или с улучшением товарища wisgest).

( 2 * b ) || ! ( 2 * b )

5

Re: VBS: для объединения CSV файлов

Можно вообще не привязываться к имени результирующего файла, а вывод направлять на консоль. Тогда (и это плюс!) вывод этого скрипта можно перенаправить на вход другого скрипта, обработчика CSV-файлов (о котором товарищ Rabi уже спрашивал)


@echo off

if "%~1" == "" (
	echo:Usage: %~n0 date
	goto :EOF
)

setlocal

set "SRC_DATE=%~1"
set "SRC_TMPL=MAG8000_*_%SRC_DATE%"

for /f "tokens=*" %%f in ( 'dir /b /s /a-d "%SRC_TMPL%"' ) do type "%%f"

Примеры использования:
1


этот-скрипт 2020-02-26 > какой-то-один-файл

2


этот-скрипт 2020-02-26 | тот-скрипт > какой-то-другой-файл
( 2 * b ) || ! ( 2 * b )

6 (изменено: Rabi, 2020-06-25 15:04:17)

Re: VBS: для объединения CSV файлов

Rumata спасибо, у меня уже есть код который читает актуальные  "csv" по дате изменения, я хотел дополнить его скриптом который после прочтения файла склеивает его с общим архивным файлом

7

Re: VBS: для объединения CSV файлов

Rabi, добрый день.

Насколько я понял, есть несколько CSV, которые нужно объединять в один файл.

1) Т.е., заголовки (первая строка) должны браться только один раз из первого файла, из остальных добавляются данные, начиная со второй строки.
В именах файлов есть ещё время, его я решил игнорировать.

2) Исходные файлы берутся из папки MAG, после обработки переносятся в папку MAG_ARHIV (чтобы далее их не дублировать).
Хотя при этом результирующий файл я каждый раз переписываю...
Возможно, не до конца разобрался, что же всё-таки нужно.

Тестовые файлы (в папке MAG) - содержимое я взял произвольное:


MAG8000_296305H319_2020-02-08 0403.csv:
	Дата;ФИО;Сумма
	08.02.2020;ИВАНОВ ИИ;1000
	08.02.2020;ПЕТРОВ ПП;2000

MAG8000_296305H319_2020-02-26 0701.csv:
	Дата;ФИО;Сумма
	26.02.2020;ИВАНОВ ИИ;111
	26.02.2020;СИДОРОВ СС;3000

Результат (в папке программы):


MAG8000_296305H319.csv:
	Дата;ФИО;Сумма
	08.02.2020;ИВАНОВ ИИ;1000
	08.02.2020;ПЕТРОВ ПП;2000
	26.02.2020;ИВАНОВ ИИ;111
	26.02.2020;СИДОРОВ СС;3000

Код программы (вызывается с параметрами, например: csv_append.vbs MAG8000_296305H319 2020-02-01 2020-02-29)


Option Explicit
On Error Resume Next

  Dim sHelpMsg : sHelpMsg = "" _
                 & vbCrLf & "Параметры: Шаблон Дата_Нач Дата_Кон" _
                 & vbCrLf & "Результат: Шаблон.csv" _
                 & vbCrLf & "Пример:    MAG8000_296305H319 2020-02-01 2020-02-29"
                 'имена файлов формата: MAG8000_296305H319_2020-02-08 0403.csv

  Const s_FldCsv = "MAG\"
  Const s_FldArh = "MAG_ARHIV\"
  Const s_CsvExt = ".csv"

  Dim goShellApp : Set goShellApp = CreateObject("Shell.Application")
  Dim goWsShell  : Set goWsShell  = CreateObject("WScript.Shell")
  Dim goFSO      : Set goFSO      = CreateObject("Scripting.FileSystemObject")
  Dim goParams   : Set goParams   = WScript.Arguments.Unnamed
  Dim gsFldWork  : gsFldWork      = goFSO.GetParentFolderName(WScript.ScriptFullName) & "\"

  Dim sTemplate, dStart, dEnd
  Dim sResult, sArhiv
  Dim sFile, oFile, sFld, sText, nTmp

  ' создание папок
  For Each sFld In Array(s_FldCsv, s_FldArh)
    goFSO.CreateFolder(sFld)
  Next 'sFld

  ' проверка на число параметров
  If goParams.Length <> 3 Then
    WScript.Echo sHelpMsg
    WScript.Quit(0)
  End If 

  ' разбор параметров
  sTemplate = goFSO.GetBaseName(Trim(goParams(0)))
  dStart    = Trim(goParams(1))
  dEnd      = Trim(goParams(2))

  sResult   = sTemplate & s_CsvExt

  ' если файл результата существует - убираем его в архивную папку
  If goFSO.FileExists(sResult) Then
    sArhiv = goFSO.BuildPath(s_FldArh, goFSO.GetFileName(sResult))
    goFSO.DeleteFile sArhiv, True
    goFSO.MoveFile sResult, sArhiv
    If goFSO.FileExists(sResult) Then
      WScript.Echo "Ошибка удаления старого файла: " & sResult
      WScript.Quit(0)
    End If
  End If

  ' обработка файлов в паке MAG\
  For Each oFile In goFSO.GetFolder(s_FldCsv).Files

    sFile = oFile.Path

    If StrComp("." & goFSO.GetExtensionName(sFile), s_CsvExt, vbTextCompare) = 0 Then

      ' имена между MAG8000_296305H319_2020-02-01 0000.csv и MAG8000_296305H319_2020-02-29 9999.csv
      If StrComp(goFSO.GetBaseName(sFile), sTemplate & "_" & dStart & " 0000" , vbTextCompare) >= 0 and _ 
         StrComp(goFSO.GetBaseName(sFile), sTemplate & "_" & dEnd   & " 9999" , vbTextCompare) <= 0 Then

        sText = ""
        With goFSO.OpenTextFile(sFile, 1) 'ForReading
          sText = .ReadAll : .Close
        End With

        ' если этот CSV не первый - убираем заголовок
        If goFSO.FileExists(sResult) Then
          nTmp = InStr(1, sText, vbCrLf, vbTextCompare)
          If nTmp <> 0 Then sText = Mid(sText, nTmp + Len(vbCrLf))
          sText = vbCrLf & sText
        End If

        ' убираем "лишний" возврат строки в конце
        If Right(sText, Len(vbCrLf)) = vbCrLf Then
          sText = Left(sText, Len(sText) - Len(vbCrLf))
        End If

        With goFSO.OpenTextFile(sResult, 8, True) 'Append, Create
          .Write(sText) : .Close
        End With

        ' убираем в архивную папку обработанный CSV
        '  1=0 если не надо удалять CSV
        If 1=1 Then
          sArhiv = goFSO.BuildPath(s_FldArh, goFSO.GetFileName(sFile))
          goFSO.DeleteFile sArhiv, True
          goFSO.MoveFile sFile, sArhiv
          If goFSO.FileExists(sFile) Then
            WScript.Echo "Ошибка удаления файла: " & sFile
            'WScript.Quit(0)
          End If
        End If

      End If
    
    End If
  Next 'oFile

  If goFSO.FileExists(sResult) Then
    sText = " создан файл: " & sResult
  Else
    sText = " файлы не найдены, результат пустой."
  End If
  WScript.Echo "По заданному периоду", dStart, " .. ", dEnd, sText

WScript.Quit(0)

8

Re: VBS: для объединения CSV файлов

andypetr
Ваш статус изменён, прошу ознакомиться.
http://yoursmileys.ru/tsmile/forum/t1230.gif