Страницы: 1
RSS
Выборка данных Из XLSX и создание нового CSV с этими данными
 
Здравствуйте. Помогите пожалуйста. Уже который день пытаюсь понять как решить задачу с помощью макроса.
Есть большой документ .xls со множенством таблиц (40 шт). Все таблицы во вкладках являются умными и очень взаимосвязаны между собой формулами, так что изменения, внесенные в первую таблицу очень влияет на все прочие. Однако, порядок столбцов и шапка остаются неизменными. Из каждой вкладки (из каждой таблицы) этого большого документа нужно изъять определенные столбцы с данными и вложить в новосозданный CSV файл.
Признаюсь, искал, но так и не нашел ответ как это сделать.
ПС: догружаю пример файлов https://cloud.mail.ru/public/3uLn/3DqoFftLQ
Изменено: restor - 02.05.2019 08:48:58
 
Здравствуйте. Вы правда думаете, что мы сможем оказать хоть какую-то помощь, кроме моральной, не видя ни структуры файла, ни образцов таблиц (сколько столбцов, как они расположены и прочие мелочи...), ни образца желаемого результата? Ну вот, положа руку на левую грудь - ответьте честно, а?
Кому решение нужно - тот пример и рисует.
 
Написал вопрос, а загрузить пример не получается. Ограничение на документ в 100кб установлено на форуме.
Дал ссылку на облачный файлообменник.
Документ XLSX - исходник
Документ CSV - результат
Столбцы, которые нужно изьять из таблиц отделены красным разделителем.
Реально что-то такое сотворить в эксцеле что бы оно само создавало документы из выбраных столбцов.
 
Цитата
restor написал:
Ограничение на документ в 100кб установлено на форуме
Ещё раз прочитайте правила в части этого ограничения.
 
restor,
Изменено: Андрей Лящук - 06.04.2019 11:03:07
 
Предлагают простой экспорт.
Я  наверное не очень понятно пояснил.
Есть документ, в котором много таблиц (в приведенном примере их только 4, но в реальном документе их 40 и более). В примере он сохранен в формате .xlsx
В каждой таблице есть группа столбцов, начиная со стоблца N, которые нужно периодически сохранять каждый в отдельный .CSV файл.
Теоретически, это можно делать и вручную, но при малейшем изменении таблицы, заново все вкладки пересохранять в CSV очень проблематично, т.к. в течение дня все таблицы могут меняться по 20-50 раз. (И после каждого изменения проводить такую операцию как выделить какую-то часть, скопировать, вставить в подготовленный CSV и пересохранять так целый день напролет не предоставляется возможным). Можно ли эту операцию по выделению и сохранению в CSV как-то автоматизировать?
 
Вместо ручного копирования и сохранения нужного столбца в csv, делайте это макросом. В чем сложность? Только я не понял, какой должен быть флаг для начала этого копирования, изменения в любой ячейки любого листа? Прямой ответ по теме - макросом можно копировать нужный столбец в отдельный лист, лист сохранять в csv.
«Бритва Оккама» или «Принцип Калашникова»?
 
Спасибо. Можете привести пример такого макроса?
Флагом для начала копирования выступает красный столбец. Все что справа от него (до начала пустых ячеек) надо копировать в CSV. Собственно, на примере первой таблицы и показан результирующий CSV файл. Приведите пожалуйста пример макроса, который мог бы из первой таблицы файла XLSX создать  такой CSV как в приведенном примере. Может я соображу и по образцу потом допишу макрос под другие таблицы из приведенного файла XLSX
 
Цитата
bedvit написал:
Только я не понял, какой должен быть флаг для начала этого копирования, изменения в любой ячейки любого листа?
Флагом для начала копирования может выступать красный столбец. Все что справа от него как раз и надо скопировать в CSV макросом. Помогите примером, пожалуйста.
 
Пример макроса. Лист Epson сохраняется как csv с именем листа в той же папке, что и рабочая книга.
Код
Sub CopySheetCsv(ByVal shName)
  Dim Path
  Path = ActiveWorkbook.Path
  
  On Error Resume Next
  Worksheets(shName).Copy  ' копируем в новую книгу
  If Err.Number <> 0 Then
    Exit Sub
  End If
  On Error GoTo 0
  
  Cells.Copy               ' меняем формулы на значения
  Range("A1").PasteSpecial Paste:=xlPasteValues
  Application.CutCopyMode = False
   
  Columns("A:M").Delete    ' удаляем лишние столбцы
  
  On Error Resume Next
  ActiveWorkbook.SaveAs Path & "\" & ActiveSheet.Name, xlCSV
  ActiveWorkbook.Close False
  On Error GoTo 0

End Sub

Sub test()

  CopySheetCsv "Epson"

End Sub
Владимир
 
Цитата
sokol92 написал:
Path & "\" & ActiveSheet.Name, xl
Спасибо большое. У меня код этот не сработал, но основная мысль понятна. Вопрос: как сделать что бы макрос выполнялся не для одной, а для всех таблиц в книге и сохранял каждую созданную таблицу в отдельный csv файл?
 
Владимир, спасибо за пример.
Тогда пример по теме - немного посложнее, но поинтересней.
Из своей рабочей обработки.
'Сохранить текущий лист Excel в текстовом формате *txt (csv), в кодировке ANSI, разделителем - запятая.
'Строки с запятыми и пробелами берутся в кавычки.*.txt сохраняется в директорию с исходным файлом.
'Имя файла = имя листа.
'Форматы числа и даты сохраняются в исходном форматировании, без преобразований.
Можно работать и с отдельным диапазоном на листе, "поправив" строки кода 30, 33, 36, 60, 61
Код
Option Explicit
'Автор Б. Виталий В. (bvv, bedvit)
'Макрос записан: 26/09/2018 (bvv)
'Редакция: 3 от 29/09/2018
'Действие:
'Сохранить текущий лист Excel в текстовом формате *txt (csv), в кодировке ANSI, разделителем - запятая.
'Строки с запятыми и пробелами берутся в кавычки.*.txt сохраняется в директорию с исходным файлом.
'Имя файла = имя листа.
'Форматы числа и даты сохраняются в исходном форматировании, без преобразований.

Sub save_as_txt()
Dim NameTemp As String, ac
Dim cRow As Long, cColumn As Long, rEnd As Long, rEndMax As Long, cEndMax As Long, cEnd As Long, arr, s, char, SheetName As String, ЗапрещённыеСимволы, t, keyDell

If ActiveWorkbook.Path = "" Then MsgBox "BVV: Для выполнения этой команды нужно, чтобы исходный файл был сохранен.", vbExclamation: Exit Sub
't = Timer
With Application: .StatusBar = "BVV: обработка данных...": .ScreenUpdating = 0: .DisplayAlerts = 0: .EnableEvents = 0: ac = .Calculation: .Calculation = -4135: End With
SheetName = ActiveSheet.name
''''''''удалим запрещенные символы файловой системы
ЗапрещённыеСимволы = Array("\", "/", ":", "*", "?", "<", ">", "|", Chr(34)) 'кавычки
For Each char In ЗапрещённыеСимволы
SheetName = Replace(SheetName, char, "_")
Next ' char
'''''''''''''''''''''''''''''''''''''''''''''''''''

NameTemp = Mid$(ActiveWorkbook.FullName, 1, Len(ActiveWorkbook.FullName) - 5) & "(" & SheetName & ")" & ".txt"
ActiveSheet.Copy
'сохраняем в значениях
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ActiveSheet.UsedRange.Select
If Selection.Count = 1 Then
    Selection.Resize(1, 2).Select ' добавляем ячейку для правильного формирования массива
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
    ReDim Preserve arr(1 To 1, 1 To 1) ' удаляем лишнюю ячейку
Else
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
End If

keyDell = Chr(16) & Chr(19) & "," & Chr(127) & Chr(23) ' ключ с запятой для кавычек в дальнейшем удаляем

rEnd = UBound(arr)
cEnd = UBound(arr, 2)

For cRow = 1 To rEnd
    For cColumn = 1 To cEnd
        If IsError(arr(cRow, cColumn)) Then 'выводим ошибки в текстовый файл не обрабатывая
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        ElseIf Not arr(cRow, cColumn) = "" Or Not IsEmpty(arr(cRow, cColumn)) Then
            If InStr(1, arr(cRow, cColumn), " ", vbTextCompare) > 0 Then
                arr(cRow, cColumn) = keyDell & arr(cRow, cColumn)
            Else
                arr(cRow, cColumn) = "'" & arr(cRow, cColumn)
            End If
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        End If
    Next
Next
Selection.Delete
Selection.Resize(rEndMax, cEndMax) = arr
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ActiveWorkbook.SaveAs FileName:=NameTemp, FileFormat:=xlCSV, CreateBackup:=False ', local:=True
ActiveWindow.Close False

'удаляем отметку в txt файле
Open NameTemp For Input As #1 'открываем файл на чтение
s = Input(LOF(1), 1) 'считываем в переменную
Close #1 ' закрываем
Application.Wait (Now + 1 / 86400) ' ждем одну секунду от закрытия до открытия этого же файла.
Open NameTemp For Output As #1 'открываем для записи
Print #1, Replace(s, keyDell, "") 'заменяем текст и записываем в файл
Close #1 'закрываем файл
''''''''''''''''
With Application: .ScreenUpdating = 1: .DisplayAlerts = 1: .EnableEvents = 1: .Calculation = ac: .StatusBar = False: End With
End Sub
Изменено: bedvit - 07.04.2019 16:58:32
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, крутой пример. однако, как сделать так что бы разделитель был вместой запятой была точка с запятой? или это настройки ОС?
 
bedvit, Хотя.. уже понял как. Достаточно раскомментировать  local:=True
Только не могу теперь разобраться как сохранять каждую таблицу из книги в отдельный файл. После запуска макроса, почему-то создается лишь один файл, сформированный из первой таблице. Если можете - подскажите мне.
 
Цитата
Однако, что у меня совсем не получается.
1. Необходимо что бы макрос затрагивал все таблицы книги и формировал столько csv документов, сколько есть всех таблиц (или же, можно все таблицы подряд вложить в один документ, с общей шапкой в первой строке, если так будет сделать проще)
2. Отфильтровать с помощью макроса все данные перед формированием CSV и исключить из обработки первые столбцы (A:T). Что бы в итоговом(-ых) документе(-ах) CSV этих столбцов не было.

Буду весьма признателен, если каким-либо образом мне сможете помочь, или хотя бы натолкнете на подобные примеры решения такого роде задач.
Спасибо.
(фрагмент из лички). Отвечу вам в исходной теме:
1. Если таблица на каждом листе отдельно, добавьте перебор по листам, для каждого запуская макрос. Если таблицы много на одном листе, тоже нужен цикл, но уже по диапазону каждой таблицы. Работать можно и с отдельным диапазоном на листе, "поправив" исходные строки кода 30, 60, 61.
В строке 30 скармливать нужный диапазон. В 60й удалить данные со всего листа, а не только с нужного диапазона. Ну и в 61 вставить с первой ячейки листа обработанный массив.
2.последний вариант решает этот вопрос (перебор по диапазонам).
Изменено: bedvit - 04.05.2019 00:56:28
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
перебор по листам, для каждого запуская макрос
Убил фактически сутки на поиск решения. Но, все старания закончились ошибками.
Никак не могу применить "перебор страниц" к уже имеющемуся коду. Особенно, когда они еще и называются не Лист1, Лист2, Лист3, а каждый совсем по-своему.
Столбцы диапазона (А:Т), которые надобно убирать в результирующем csv, прописал так

Код
    .Columns("A:T").Select
     Selection.Delete Shift:xlLeft


 Однако, почему-то не удаляются эти столбцы. Зато, решил проблему фильтрации пустых строк. Так что эту проблему можно будет пока оставить на "сладкое", либо еще над ней посижу несколько выходных.

Не хватает мне практики в этих областях, хотя, в детстве на VBA какие-то программы писал для решения уравнений)) Сейчас спустя годы почему-то думал что разберусь без проблем. Ошибся.
Если есть еще вариант как мне помочь, буду очень признателен.

Файл загрузить не получается - очень большой. Потому, оставил тут https://yadi.sk/d/aUiqBjMz1YHC_A
Поубирал большинство таблиц из документа, оставил только 4шт для опытов.
Изменено: restor - 05.05.2019 03:25:54
 
Цитата
restor написал:
почему-то не удаляются эти столбцы
- удаляются. Но сразу этот выделенный диапазон заполняется данными массива. Зачем  - не вникал.
 
Цитата
restor написал:
Файл загрузить не получается - очень большой.
А большой и не нужен. Создайте маленький файл-пример с аналогичной структурой.
 
restor, фал пример в рабочей структуре, но с меньшим количеством данных не помешал бы. Но раз зашел в тему, то вот:
Код
Option Explicit
'Автор Б. Виталий В. (bvv, bedvit)
'Макрос записан: 26/09/2018 (bvv)
'Редакция: 4 от 05/05/2019
'Действие:
'Сохраняет все листы книги, перебирая
'Сохраняет лист Excel в текстовом формате *txt (csv), в кодировке ANSI, разделителем - точка с запятой.
'Строки с "точкой с запятой" и пробелами берутся в кавычки.*.txt сохраняется в директорию с исходным файлом.
'Имя файла = имя листа.
'Форматы числа и даты сохраняются в исходном форматировании, без преобразований.
'удаляются Columns("A:T")

Sub save_as_txt()
Dim NameTemp As String, ac
Dim cRow As Long, cColumn As Long, rEnd As Long, rEndMax As Long, cEndMax As Long, cEnd As Long, arr, s, char, SheetName As String, ЗапрещённыеСимволы, keyDell
Dim WS As Worksheet

If ActiveWorkbook.Path = "" Then MsgBox "BVV: Для выполнения этой команды нужно, чтобы исходный файл был сохранен.", vbExclamation: Exit Sub
With Application: .StatusBar = "BVV: обработка данных...": .ScreenUpdating = 0: .DisplayAlerts = 0: .EnableEvents = 0: ac = .Calculation: .Calculation = -4135: End With

For Each WS In ActiveWorkbook.Worksheets 'цикл по листам
SheetName = WS.Name
''''''''удалим запрещенные символы файловой системы
ЗапрещённыеСимволы = Array("\", "/", ":", "*", "?", "<", ">", "|", Chr(34)) 'кавычки
For Each char In ЗапрещённыеСимволы
SheetName = Replace(SheetName, char, "_")
Next ' char
'''''''''''''''''''''''''''''''''''''''''''''''''''
 
NameTemp = Mid$(ActiveWorkbook.FullName, 1, Len(ActiveWorkbook.FullName) - 5) & "(" & SheetName & ")" & ".txt"
WS.Copy
Cells.Copy
Cells.PasteSpecial Paste:=xlPasteValues
ActiveSheet.Columns("A:T").Delete
'сохраняем в значениях
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ActiveSheet.UsedRange.Select
If Selection.Count = 1 Then
    Selection.Resize(1, 2).Select ' добавляем ячейку для правильного формирования массива
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
    ReDim Preserve arr(1 To 1, 1 To 1) ' удаляем лишнюю ячейку
Else
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
End If
 
keyDell = Chr(16) & Chr(19) & ";" & Chr(127) & Chr(23) ' ключ с "точка с запятой" для взятия пробелов в кавычки в дальнейшем удаляем
 
rEnd = UBound(arr)
cEnd = UBound(arr, 2)
rEndMax = 0
cEndMax = 0
For cRow = 1 To rEnd
    For cColumn = 1 To cEnd
        If IsError(arr(cRow, cColumn)) Then 'выводим ошибки в текстовый файл не обрабатывая
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        ElseIf Not arr(cRow, cColumn) = "" Or Not IsEmpty(arr(cRow, cColumn)) Then
            If InStr(1, arr(cRow, cColumn), " ", vbTextCompare) > 0 Then
                arr(cRow, cColumn) = keyDell & arr(cRow, cColumn)
            Else
                arr(cRow, cColumn) = "'" & arr(cRow, cColumn)
            End If
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        End If
    Next
Next
ActiveSheet.Cells.Delete
ActiveSheet.Cells(1, 1).Resize(rEndMax, cEndMax) = arr
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ActiveWorkbook.SaveAs Filename:=NameTemp, FileFormat:=xlCSV, CreateBackup:=False, local:=True
'закомментировать local:=True - разделитель запятая, и не забыть поправить keyDell для обработки пробелов
ActiveWindow.Close False
 
'удаляем отметку в txt файле
Open NameTemp For Input As #1 'открываем файл на чтение
s = Input(LOF(1), 1) 'считываем в переменную
Close #1 ' закрываем
'Application.Wait (Now + 1 / 86400) ' ждем одну секунду от закрытия до открытия этого же файла.
Open NameTemp For Output As #1 'открываем для записи
Print #1, Replace(s, keyDell, "") 'заменяем текст и записываем в файл
Close #1 'закрываем файл
''''''''''''''''
Next

With Application: .ScreenUpdating = 1: .DisplayAlerts = 1: .EnableEvents = 1: .Calculation = ac: .StatusBar = False: End With
End Sub
Изменено: bedvit - 05.05.2019 15:42:09
«Бритва Оккама» или «Принцип Калашникова»?
 
Изменив в коде строку 46 (на запятую) и строку 71 (закомментировав , local:=True) легко переходим на разделитель запятая.
«Бритва Оккама» или «Принцип Калашникова»?
 
Универсальный вариант, меняем значение переменной Р_Т_З (разделитель "точка с запятой") и получаем нужный разделитель.
Код
Option Explicit
'Автор Б. Виталий В. (bvv, bedvit)
'Макрос записан: 26/09/2018 (bvv)
'Редакция: 5 от 05/05/2019
'Действие:
'Сохраняет все листы книги, перебирая
'Сохраняет лист Excel в текстовом формате *txt (csv), в кодировке ANSI, с нужным разделителем - запятая или точка с запятой.
'Строки содержащие символ разделителя и пробел - берутся в кавычки.
'*.txt сохраняется в директорию с исходным файлом.
'Имя файла = имя листа.
'Форматы числа и даты сохраняются в исходном форматировании, без преобразований.
'удаляются Columns("A:T")

Sub save_as_txt()
Dim NameTemp As String, ac, WS As Worksheet, Р_Т_З As Boolean
Dim cRow As Long, cColumn As Long, rEnd As Long, rEndMax As Long, cEndMax As Long, cEnd As Long, arr, s, char, SheetName As String, ЗапрещённыеСимволы, keyDell

Р_Т_З = True 'если нужен разделитель "точка с запятой", то True, если "запятая" - False

If ActiveWorkbook.Path = "" Then MsgBox "BVV: Для выполнения этой команды нужно, чтобы исходный файл был сохранен.", vbExclamation: Exit Sub
With Application: .StatusBar = "BVV: обработка данных...": .ScreenUpdating = 0: .DisplayAlerts = 0: .EnableEvents = 0: ac = .Calculation: .Calculation = -4135: End With

For Each WS In ActiveWorkbook.Worksheets 'цикл по листам
SheetName = WS.Name
''''''''удалим запрещенные символы файловой системы
ЗапрещённыеСимволы = Array("\", "/", ":", "*", "?", "<", ">", "|", Chr(34)) 'кавычки
For Each char In ЗапрещённыеСимволы
SheetName = Replace(SheetName, char, "_")
Next ' char
'''''''''''''''''''''''''''''''''''''''''''''''''''
 
NameTemp = Mid$(ActiveWorkbook.FullName, 1, Len(ActiveWorkbook.FullName) - 5) & "(" & SheetName & ")" & ".txt"
WS.Copy
Cells.Copy
Cells.PasteSpecial Paste:=xlPasteValues
ActiveSheet.Columns("A:T").Delete
'сохраняем в значениях
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ActiveSheet.UsedRange.Select
If Selection.Count = 1 Then
    Selection.Resize(1, 2).Select ' добавляем ячейку для правильного формирования массива
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
    ReDim Preserve arr(1 To 1, 1 To 1) ' удаляем лишнюю ячейку
Else
    arr = Selection 'Intersect(ActiveSheet.UsedRange, Selection)
End If
 
keyDell = Chr(16) & Chr(19) & IIf(Р_Т_З, ";", ",") & Chr(127) & Chr(23) ' ключ с разделителем для взятия пробелов в кавычки в дальнейшем удаляем

rEnd = UBound(arr)
cEnd = UBound(arr, 2)
rEndMax = 0
cEndMax = 0
For cRow = 1 To rEnd
    For cColumn = 1 To cEnd
        If IsError(arr(cRow, cColumn)) Then 'выводим ошибки в текстовый файл не обрабатывая
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        ElseIf Not arr(cRow, cColumn) = "" Or Not IsEmpty(arr(cRow, cColumn)) Then
            If InStr(1, arr(cRow, cColumn), " ", vbTextCompare) > 0 Then
                arr(cRow, cColumn) = keyDell & arr(cRow, cColumn)
            Else
                arr(cRow, cColumn) = "'" & arr(cRow, cColumn)
            End If
            rEndMax = Application.Max(cRow, rEndMax)
            cEndMax = Application.Max(cColumn, cEndMax)
        End If
    Next
Next
ActiveSheet.Cells.Delete
ActiveSheet.Cells(1, 1).Resize(rEndMax, cEndMax) = arr
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

If Р_Т_З Then
ActiveWorkbook.SaveAs Filename:=NameTemp, FileFormat:=xlCSV, CreateBackup:=False, local:=True
Else
ActiveWorkbook.SaveAs Filename:=NameTemp, FileFormat:=xlCSV, CreateBackup:=False, local:=False
End If

ActiveWindow.Close False
 
'удаляем отметку в txt файле
Open NameTemp For Input As #1 'открываем файл на чтение
s = Input(LOF(1), 1) 'считываем в переменную
Close #1 ' закрываем
'Application.Wait (Now + 1 / 86400) ' ждем одну секунду от закрытия до открытия этого же файла.
Open NameTemp For Output As #1 'открываем для записи
Print #1, Replace(s, keyDell, "") 'заменяем текст и записываем в файл
Close #1 'закрываем файл
''''''''''''''''
Next

With Application: .ScreenUpdating = 1: .DisplayAlerts = 1: .EnableEvents = 1: .Calculation = ac: .StatusBar = False: End With
End Sub
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, спасибо большое. Долгое время не мог понять почему не работает. Оказалось, надо было все-таки вопрос с фильтрами порешать. Вот сейчас этот вопрос штудирую. Вы bedvit, конечно, профи высокого уровня. Мне далеко до Вас
Страницы: 1
Наверх