Войти

Показать полную графическую версию : [решено] CMD/BAT - Скрипт, который считывает количество данных из разных таблиц Excel


romfus
19-04-2018, 14:04
Добрый день. Вот такая задачка. Имеются несколько десятков excel файлов с разными именами 34S_1 - 999999_19.04.2018_14.xls, 34S_400000 - 400138_19.04.2018_1.xls, 34S_400139 - 404622_19.04.2018_9.xls например. В каждой из этих таблиц имеются данные ( индекса городов ) Можно ли сделать так чтобы при запуске скрипта выводилось сообщение - Введите индекс и после ввода индекса выводилось количество данных с этим индексом со всех xls файлов? Думаю имена файлов xls неважно? Достаточно просто с:/путь/*.xls указать

Iska
19-04-2018, 14:08
Думаю имена файлов xls неважно? Достаточно просто с:/путь/*.xls указать »
То есть, подразумевается, что мы перебираем все Рабочие книги в указанном каталоге, так?

Имеются несколько десяткой excel файлов »
Упакуйте несколько образцов файлов в архив и приложите к сообщению, либо выложите на обменник/Яндекс.Диск.

выводилось количество данных с этим индексом »
Что подразумевается под «количеством данных»?

romfus
19-04-2018, 14:15
Вот пример одного файла, структура у них у всех одинакова. Так да, перебираем все рабочие книги. Посмотрите пример файла, думаете поймете о чем я. В файле много индексов. вводим один индекс и скрипт считывает сколько раз этот индекс повторился в книге и выдает количество

romfus
19-04-2018, 14:23
вот 2 файл для примера

Iska
19-04-2018, 16:04
Вот пример одного файла, »
Ну, почему, почему всегда одно и то же, одно и то же. Вам так сложно упаковать несколько разных файлов в архив и выложить?

повторился в книге »
Вы хотели сказать «в книгах»?

Ну, вот как-то так я себе это представляю (на WSH):
Option Explicit

Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = 1


Dim strSourceFolder
Dim strPostCode

Dim objFSO
Dim objFile

Dim objConnection
Dim objCatalog
Dim objTable
Dim objRecordset

Dim intTotalOccuped


If WScript.Arguments.Count = 1 Then
strSourceFolder = WScript.Arguments.Item(0)

Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

If objFSO.FolderExists(strSourceFolder) Then
strPostCode = "123456"
strPostCode = InputBox("Введите почтовый индекс:", "Введите почтовый индекс", strPostCode)

Set objConnection = WScript.CreateObject("ADODB.Connection")
Set objRecordset = WScript.CreateObject("ADODB.Recordset")
Set objCatalog = WScript.CreateObject("ADOX.Catalog")

WScript.Echo "Почтовый индекс [" & strPostCode & "] встречается в:"
WScript.Echo "------------------------------------------------------------------"

intTotalOccuped = 0

For Each objFile In objFSO.GetFolder(strSourceFolder).Files
If StrComp(objFSO.GetExtensionName(objFile.Name), "xls", vbTextCompare) = 0 Then
WScript.Echo "[" & objFile.Path & "]"

With objConnection
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Properties.Item("Extended Properties").Value = "Excel 8.0;HDR=Yes;IMEX=1"
.Open objFile.Path

objCatalog.ActiveConnection = objConnection

For Each objTable In objCatalog.Tables
If StrComp(objTable.Type, "TABLE", vbTextCompare) = 0 Then
With objRecordset
.Open "SELECT indexto FROM [" & objTable.Name & "] WHERE indexto = '" & strPostCode & "'", objConnection, adOpenStatic, adLockOptimistic, adCmdText
intTotalOccuped = intTotalOccuped + .RecordCount
WScript.Echo vbTab & "[" & objTable.Name & "] - " & .RecordCount & " раз(а)"
.Close
End With
End If
Next

objCatalog.ActiveConnection = Nothing

.Close
End With
End If
Next

WScript.Echo "------------------------------------------------------------------"
WScript.Echo "Всего " & intTotalOccuped & " раз(а)"

Set objCatalog = Nothing
Set objRecordset = Nothing
Set objConnection = Nothing
Else
WScript.Echo "Source folder [" & strSourceFolder & "] not found."
WScript.Quit 2
End If
Else
WScript.Echo "Usage: cscript.exe //nologo """ & WScript.ScriptFullName & """ <Source folder>"
WScript.Quit 1
End If

WScript.Quit 0

https://i.imgur.com/pVEnRQl.png

Путь к целевому каталогу указывается аргументом скрипта. Скорректируйте строку подключения под Ваш драйвер OLEDB. В случае x64 ОС и x86 версии драйвера (как, например, в моём примере) используйте x86-версию исполнителя cscript.exe из каталога %SystemRoot%\SysWOW64.

Iska
20-04-2018, 06:26
Поправил недоработку в предыдущем сообщении, оставшуюся от отладки (не везде заменил прямой константный путь на переменную strSourceFolder).

romfus
20-04-2018, 14:20
Спасибо. Что-то у меня cscript не запускается.

Iska
20-04-2018, 14:23
Что-то у меня cscript не запускается. »
Продемонстрируйте.

romfus
20-04-2018, 14:29
Продемонстрируйте. »
Iska, я скорее всего неправильно понял что-то. При запуске скрипта выдает Echo "Usage: cscript.exe //nologo """ & WScript.ScriptFullName & """ <Source folder>"

Iska
20-04-2018, 14:38
выдает Echo "Usage: cscript.exe //nologo """ & WScript.ScriptFullName & """ <Source folder>" »
В сказки не верю. Покажите скриншот.

При запуске скрипта »
Опишите/продемонстрируйте, как Вы его запускаете.

romfus
20-04-2018, 14:43
Опишите/продемонстрируйте, как Вы его запускаете. »
Я ваш код скопировал в текстовый файл сохранил как vbs и при запуске такая ошибка. Видимо я что-то опустил. Я просто в wsh не силен. Что-то видимо нужно где-то еще дополнительно указать, чего я не сделал как я понял

Iska
20-04-2018, 14:54
Я ваш код скопировал в текстовый файл сохранил как vbs »
Здесь правильно.

и при запуске такая ошибка. »
Это сообщение о том, как следует осуществлять запуск скрипта правильно.

Откройте командную строку. Напишите в ней cscript.exe //nologo, добавьте пробел. Перетащите туда же скрипт из Проводника, добавьте ещё пробел. Теперь перетащите туда же из Проводника папку, в которой находятся файлы, которые требуется обработать. Нажмите Enter.

Если увидите сообщение вида «ADODB.Properties: Не удается найти указанный поставщик. Вероятно, он установлен неправильно» и у Вас x64 ОС — пишете не просто cscript.exe, а %SystemRoot%\SysWOW64\cscript.exe и т.д.

romfus
20-04-2018, 15:01
Здесь правильно. »Спасибо работает. А можно ли
R34ROMANOVSKIY4 C:\Users\Alexander.Romanovski>cscript.exe //nologo C:\Users\Alexander.Romanovski\Des
ktop\0001.vbs D:\IVC\Operators\Printer\20.04.2018
Закрепить в самом скрипте? чтобы при запуске сразу выводилось окно с просьбой ввести индекс?

Iska
20-04-2018, 15:08
romfus, Вы хотите сказать, что каталог с файлами всегда будет один и тот же? Создайте ярлык вида:
C:\Windows\System32\cscript.exe //nologo "C:\Users\Alexander.Romanovski\Desktop\0001.vbs" "D:\IVC\Operators\Printer\20.04.2018"

romfus
20-04-2018, 15:17
C:\Windows\System32\cscript.exe //nologo "C:\Users\Alexander.Romanovski\Desktop\0001.vbs" "D:\IVC\Operators\Printer\20.04.2018" »
а если созданный ярлык при запуске закрывается сразу? То есть появляется окно ввести индекс после ввода все счиытвает и моментально закрывается

Iska
20-04-2018, 15:43
а если созданный ярлык при запуске закрывается сразу? То есть появляется окно ввести индекс после ввода все счиытвает и моментально закрывается »
Виноват, не подумал. Приношу Вам свои извинения.

Попробуйте задать такую строку в ярлыке:
"%comspec%" /c"C:\Windows\System32\cscript.exe //nologo "C:\Users\Alexander.Romanovski\Desktop\0001.vbs" "D:\IVC\Operators\Printer\20.04.2018" & pause"
Если требуются какие-либо манипуляции с окном — тогда так:
"%comspec%" /k"C:\Windows\System32\cscript.exe //nologo "C:\Users\Alexander.Romanovski\Desktop\0001.vbs" "D:\IVC\Operators\Printer\20.04.2018""
romfus, общий принцип и вид вывода — это то, что Вам требовалось? Более ничего менять/настраивать не надо?

romfus
20-04-2018, 18:54
Все отлично. Спасибо!

megaloman
21-04-2018, 15:56
romfus, Я, наверное, лезу не в своё дело, но постановку задачи я переосмыслил.inName = "Z:\Soft_In"

With WScript.Arguments
If .Count <> 0 Then inName = .Item(0)
End With

Set FSO = CreateObject("Scripting.FileSystemObject")

On Error Resume Next
Set nDir = FSO.GetFolder(inName)
If Err.Number <> 0 Then
MsgBox inName + vbCrLf + Err.Description
WScript.Quit 1
End If
On Error GoTo 0

Tit = Array("num", "indexto", "region", "area", "city", "adres", "adresat", "mass", "value", "payment", "comment")
NTit = UBound(Tit) - LBound(Tit)

inExt = "xls"
Rng1 = "A1"
Rng2 = "B1"

Set AllFiles = nDir.Files

With CreateObject("Excel.Application")
.Visible = True
.Workbooks.Add

CN = .Range(Rng1).Offset(0, NTit).Address
.Range(Rng1 + ":" + CN).Value = Tit
Cont = .Range(Rng2)
ii = 0

For Each iFile In AllFiles
If LCase(inExt) = LCase(FSO.GetExtensionName(iFile)) Then
.Workbooks.Open (iFile)
i = 0
If .Range(Rng2) = Cont Then
Do
If Trim(.Range(Rng2).Offset(i + 1, 0)) = "" Then Exit Do
i = i + 1
Loop
R0 = .Range(Rng1).Offset(1, 0).Address
RN = .Range(Rng1).Offset(i, NTit).Address
Mas = .Range(R0 + ":" + RN)
End If
.ActiveWorkbook.Close
.Range(R0 + ":" + RN).Offset(ii, 0).NumberFormat = "@"
.Range(R0 + ":" + RN).Offset(ii, 0) = Mas
ii = ii + i
End If
Next
R0 = .Range(Rng2).Offset(1, 0).Address
RN = .Range(Rng2).Offset(ii, 0).Address
RF = .Range(Rng2).Offset(ii + 1, 0).Address

.ActiveWindow.SplitRow = 1
.ActiveWindow.FreezePanes = True

.Columns("A:A").EntireColumn.AutoFit
.Range(Rng2).AutoFilter
.Range(RF).FormulaLocal = "=ПРОМЕЖУТОЧНЫЕ.ИТОГИ(3;" + R0 + ":" + RN + ")"
.Rows(CStr(.Range(Rng2).Row)).Insert (xlDown)
.Range(Rng2).FormulaLocal = "=" + .Range(RF).Offset(1, 0).Address

End With затем накладывает на нее фильтр и прописывает формулу подсчета отфильтрованных значений. Если данных не слишком много, это сработает.
Что плохо в этом решении: конечно, сборка отработает медленнее. Я не знаю, сколько строк получится в итоговой таблице.
Что хорошо: после сборки при необходимости выборки нескольких индексов этот процесс быстр и удобен. Плюс, имеем полную инфу по каждому адресату. Можем выбирать сразу несколько индексов и подсчитывать их количество.
Можем выбрать инфу и по другому полю.
Обрабатываемую папку можно указать явно, например, как сейчас: inName = "Z:\Soft_In" (пропишИте своё!).
Однако, если при запуске скрипта папку указать в аргументе, то возьмётся не явное описание из текста скрипта, а то, что в аргументе.
Как следствие, на этот скрипт можно создать, например, на рабочем столе значок, и затягивать на него из проводника нужную папку .




© OSzone.net 2001-2012