Текущее время: Пн, авг 04 2025, 21:56

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 09:42 
Директор
Директор

Зарегистрирован:
Чт, апр 16 2009, 13:30
Сообщения: 784
Пол: Мужской
Добрый день, уважаемые коллеги!

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

Никак не удается добиться, чтобы макрос считал количество строк в верхней таблице и вставлял нижнюю сразу же после верхней, без промежутков.
Может кто-то уже сталкивался с чем-то подобным?

пока что есть следующий код:

Sub copymacro(ParamArray varname())
Dim resultArea As Range
Set resultArea = varname(1)

Dim srcws As Worksheet
Dim destws As Worksheet
Dim src_row As Integer, src_col As Integer, dest_row As Integer, dest_col As Integer, n As Integer

Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual

If varname(0) = "DP_1" Then
Set srcws = ThisWorkbook.Worksheets("Лист1")
Set destws = ThisWorkbook.Worksheets("Итоговый лист")
destws.Activate
'Копируем из src_row = 1 src_col = 1
'Копируем в dest_row = 6 dest_col = 2
Call ClearForm(destws, dest_row, 1)
If IsEmpty(resultArea.Cells(src_row, 1)) Then
destws.Range("A" & dest_row).Value = "Данные отсутствуют!"
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Exit Sub
End If

Call CopyData(resultArea, src_row, src_col, destws, dest_row, dest_col, -1, resultArea.Columns.Count - src_col + 1)

Call FormatForm(destws, dest_row)
End If
If varname(0) = "DP_2" Then
Set srcws = ThisWorkbook.Worksheets("Лист 2")
Set destws = ThisWorkbook.Worksheets("Итоговый лист")
destws.Activate
'Копируем из src_row = 1 src_col = 1
'Копируем в dest_row = 18 dest_col = 2
If IsEmpty(resultArea.Cells(src_row, 1)) Then
destws.Range("A" & dest_row).Value = "Данные отсутствуют!"
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Exit Sub
End If
Call CopyData(resultArea, src_row, src_col, destws, dest_row, dest_col, -1, resultArea.Columns.Count - src_col + 1)
Call FormatForm(destws, dest_row)
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
End Sub


Заранее спасибо!


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 10:11 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2008, 07:22
Сообщения: 163
Откуда: Ektb
Пол: Мужской
Приветствую!

Если я правильно понял, то макрос отрабатывает при открытии книги. Предлагаю следующий алгоритм:
1. в макросе при открытии определять координаты обеих таблиц и записывать их, допустим, в массив;
2. в последнем вызове макроса (читай для поседней таблицы) вызывать свою процедуру;
3. в процедуре копировать/вставлять таблицы доставая их координаты из массива (и, соответственно, вычисляя количество строк) удобным для Вас способом.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 10:58 
Директор
Директор

Зарегистрирован:
Чт, апр 16 2009, 13:30
Сообщения: 784
Пол: Мужской
ash написал:
Приветствую!

Если я правильно понял, то макрос отрабатывает при открытии книги. Предлагаю следующий алгоритм:
1. в макросе при открытии определять координаты обеих таблиц и записывать их, допустим, в массив;
2. в последнем вызове макроса (читай для поседней таблицы) вызывать свою процедуру;
3. в процедуре копировать/вставлять таблицы доставая их координаты из массива (и, соответственно, вычисляя количество строк) удобным для Вас способом.


спасибо, но, честно говоря, я не знаю, как написать такой код.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 11:09 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Пт, авг 04 2006, 20:56
Сообщения: 1006
Откуда: 37 МИКРОРАЙОН
Пол: Мужской
vtb написал:
спасибо, но, честно говоря, я не знаю, как написать такой код.
Посмотрите вот здесь.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 13:07 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2008, 07:22
Сообщения: 163
Откуда: Ektb
Пол: Мужской
vtb написал:
спасибо, но, честно говоря, я не знаю, как написать такой код.


Вот что я имел ввиду:
1. Макрос при открытии книги (отрабатывает равное количеству табличных запросов в книге раз):
Code:
Public Const qCnt As Integer = 4                'количество запросов
Public arrID(1 To qCnt, 1 To 5) As Variant      'Массив с координатами запросов
Public i As Integer                             'счетчик

Public Sub SAPBExOnRefresh(queryID As String, resultArea As Range)

  i = i + 1
  With resultArea                               'создаем массив координат запросов
    arrID(i, 1) = queryID                       ' имя запроса
    arrID(i, 2) = .Row                          ' первая строка
    arrID(i, 3) = .Column                       ' первый столбец
    arrID(i, 4) = .Row + .Rows.Count - 1        ' последняя строка
    arrID(i, 5) = .Column + .Columns.Count - 1  ' последний столбец   
  End With
 
  If i = qCnt Then      'если активный запрос - последний
    i = 0               'обнуление счетчика запросов для последующего запуска
    'Call ....          'Запуск процедуры копирования таблиц
  End If
End Sub


Далее, в макрос вставляем условие, если запрос последний, то запускаем свою процедуру копирования.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 13:25 
Директор
Директор

Зарегистрирован:
Чт, апр 16 2009, 13:30
Сообщения: 784
Пол: Мужской
ROKO написал:
vtb написал:
спасибо, но, честно говоря, я не знаю, как написать такой код.
Посмотрите вот здесь.


спасибо!


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 13:26 
Директор
Директор

Зарегистрирован:
Чт, апр 16 2009, 13:30
Сообщения: 784
Пол: Мужской
ash написал:
vtb написал:
спасибо, но, честно говоря, я не знаю, как написать такой код.


Вот что я имел ввиду:
1. Макрос при открытии книги (отрабатывает равное количеству табличных запросов в книге раз):
Code:
........................................


Далее, в макрос вставляем условие, если запрос последний, то запускаем свою процедуру копирования.


Огромное спасибо! Будем пробовать!


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:09 
Специалист
Специалист

Зарегистрирован:
Вт, авг 21 2007, 18:36
Сообщения: 133
Последовательность вызова макросов определяется через номер его привязку к грид.
Просто нужно писать количество строк отчета 1 на скрытый лист, и когда макрос отрабатывает второй раз, считывать это количество и суммировать с текущим.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:15 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Вт, окт 11 2005, 12:10
Сообщения: 687
Откуда: Москва
Пол: Мужской
Мои 5 копеек. Как бы сделал я:
1. Создал бы два именованных диапазона на листе, где сливаются отчеты.
2. Можно даже смело назвать именованные диапазоны как провайдеры в книге DP_1 и DP_2
3. В колбеке я бы очищал диапазон соответствующий провайдеру от данных, потом добавлял или удалял из него строки до количества строк в отчете.
4. После приведения количества строк в соответствие -- область заполнить данными.

Критика предложенных решений:

1. Все предложенные решения оперируют несуществующим понятием "последний вызов". На практике последний вызов совершается для первого добавленного в книгу отчета. Но все равно стремный вариант. Непонятно зачем на это опираться.

2. Внутренние массивы неприятны тем, что форматирование придется создавать руками, а не копировать из готовых и отформатированных Bex-отчетов, и если есть валюта и единица измерения, вообще все кодоемко будет.

3. Избавьтесь от такой конструкции:
Code:
Set destws = ThisWorkbook.Worksheets("Итоговый лист")
Привязывайтесь к листу любыми другими способами.

4. Для отрубания реакций экселя используйте только конструкцию с обработкой ошибок, иначе эксель будет "подвисать":
Code:
Sub Output(ByVal Text As String, ByVal Level As Integer)
       
    If Not (Err Is Nothing) Then
        If Err.Number <> 0 Then
            Text = Text & _
                vbCrLf & "Номер: " & Err.Number & _
                vbCrLf & "Описание: " & Err.Description & _
                vbCrLf & "Место возникновения: " & Err.Source
            Level = vbCritical
        End If
    End If
   
    Call MsgBox(Text, vbOKOnly + Level, MsgBoxTitle)
   
End Sub

Sub ExlUnfreeze()
    Application.Interactive = True
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
End Sub
....
    Application.Interactive = False
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual     
   
    On Error GoTo ExitCallBack
....
   
ExitCallBack:
   
    If Err.Number > 0 Then
        ExlUnfreeze
        Output "Ошибка в работе макроса.", vbCritical
    Else
        ExlUnfreeze
    End If
   
    On Error GoTo 0

Ходы конем:
1. Почему не получается сделать два отчета друг под другом с существенным запасом пустых строк и пустые строки скрывать?
2. Почему не получается приклеивать второй отчет к первому, а нужно именно слияние в сторонке?

_________________
Глаза боятся, а руки крюки


Последний раз редактировалось G Ср, окт 19 2011, 15:27, всего редактировалось 1 раз.

Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:21 
Специалист
Специалист

Зарегистрирован:
Вт, авг 21 2007, 18:36
Сообщения: 133
На счет последнего вызова, Я проверял:
Последовательность вызова определяется номером грид, самым последним вызывается 1й грид.
Если в книге 3 инфопровайдера, и два грида, то макрос отработает два раза. Последовательность описана выше.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:26 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Вт, окт 11 2005, 12:10
Сообщения: 687
Откуда: Москва
Пол: Мужской
bream написал(а):
На счет последнего вызова, Я проверял:
Последовательность вызова определяется номером грид, самым последним вызывается 1й грид.
Если в книге 3 инфопровайдера, и два грида, то макрос отработает два раза. Последовательность описана выше.

Спасибо, информация ценная.
Тогда ход конем № 2 становится самым простым решением, если не требуется преобразования данных :)

_________________
Глаза боятся, а руки крюки


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:29 
Директор
Директор

Зарегистрирован:
Чт, апр 16 2009, 13:30
Сообщения: 784
Пол: Мужской
G написал:
Мои 5 копеек. Как бы сделал я:
1. Создал бы два именованных диапазона на листе, где сливаются отчеты.
2. Можно даже смело назвать именованные диапазоны как провайдеры в книге DP_1 и DP_2
3. В колбеке я бы очищал диапазон соответствующий провайдеру от данных, потом добавлял или удалял из него строки до количества строк в отчете.
4. После приведения количества строк в соответствие -- область заполнить данными.

Критика предложенных решений:

1. Все предложенные решения оперируют несуществующим понятием "последний вызов". На практике последний вызов совершается для первого добавленного в книгу отчета. Но все равно стремный вариант. Непонятно зачем на это опираться.

2. Внутренние массивы неприятны тем, что форматирование придется создавать руками, а не копировать из готовых и отформатированных Bex-отчетов, и если есть валюта и единица измерения, вообще все кодоемко будет.

3. Избавьтесь от такой конструкции:
Code:
Set destws = ThisWorkbook.Worksheets("Итоговый лист")
Привязывайтесь к листу любыми другими способами.

4. Для отрубания реакций экселя используйте только конструкцию с обработкой ошибок, иначе эксель будет "подвисать":
Code:
Sub Output(ByVal Text As String, ByVal Level As Integer)
       
..........................................

Ходы конем:
1. Почему не получается сделать два отчета друг под другом с существенным запасом пустых строк и пустые строки скрывать?
2. Почему не получается приклеивать второй отчет к первому, а нужно именно слияние?


большое спасибо!

насчет ходов конем:
1 - потому что количество строк в верхней таблице будет все время разное.
2 - не очень понял. нужно именно приклеивать, но на отдельном листе.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 15:32 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Вт, окт 11 2005, 12:10
Сообщения: 687
Откуда: Москва
Пол: Мужской
vtb написал:
1. не получается - потому что количество строк в верхней таблице будет все время разное.
Поэтому и предлагается сделать, например, 10 000 пустых строк.
И сделать их высоту нулевую. И в колбеке смотреть какие скрыть, а какие показать. И никаких грязных манипуляций данными :)

vtb написал:
2 - не очень понял. нужно именно приклеивать, но на отдельном листе.
Имеется ввиду, что пользователь смотрит на лист где есть грид с первым отчетом, к которому снизу макросом дописаны данные второго отчета.
Зачем дополнительный лист?

_________________
Глаза боятся, а руки крюки


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 19:29 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2008, 07:22
Сообщения: 163
Откуда: Ektb
Пол: Мужской
Итак, подискутируем.

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

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


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Макрос для копирования и совмещения динамических таблиц
СообщениеДобавлено: Ср, окт 19 2011, 21:28 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Вт, окт 11 2005, 12:10
Сообщения: 687
Откуда: Москва
Пол: Мужской
Замонали.

Есть 4 области:
data_t - отчет, который нужно поставить сверху, в реальном примере не нужен.
data_b - отчет, который нужно поставить снизу, в реальном примере не нужен.
top_area - область, куда помещать верхний отчет
bottom_area - область, куда помещать нижний отчет
Code:
'Sub Callback(ParamArray varname())
Sub Callback(Nm As String)
    Dim QueryRange As Range
    Dim AreaRange As Range
    Dim Area As String
    Set QueryRange = ThisWorkbook.Names(Nm).RefersToRange
'    Set QueryRange = varname(1)
   
    Select Case Nm ' varname(0)
        Case "data_t" ' "DP_1"
            Area = "top_area"
        Case "data_b" ' "DP_2"
           Area = "bottom_area"
        Case Else
            Exit Sub   
    End Select
           
    Set AreaRange = ThisWorkbook.Names(Area).RefersToRange
    AreaRange.ClearContents
    AreaRange.ClearFormats

    Do While AreaRange.Rows.Count < QueryRange.Rows.Count
        AreaRange.Rows(1).Insert (xlShiftDown)
        Range(AreaRange.Offset(-1, 0), AreaRange.Cells(AreaRange.Rows.Count, AreaRange.Columns.Count)).Name = Area
        Set AreaRange = ThisWorkbook.Names(Area).RefersToRange
    Loop

    Do While AreaRange.Rows.Count > QueryRange.Rows.Count
        AreaRange.Rows(1).Delete (xlShiftUp)
    Loop
   
    QueryRange.Copy (AreaRange.Cells(1, 1))
   
End Sub


Sub TST()
    Callback ("data_b")
    Callback ("data_t")
End Sub


Если надо выслать тестовую книжку, скажите емыл.

PS. От циклов можно избавиться, если отчеты большие.

_________________
Глаза боятся, а руки крюки


Принять этот ответ
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB