ПРостенький макрос из excle в Libre

Автор kroush, 25 ноября 2023, 14:54

0 Пользователи и 1 гость просматривают эту тему.

kroush

Добрый день, есть простенький макрос для проверки на совпадения и копирования. Был написан в Excel, помогите его адаптировать под libre
Sub copy()
    For j = 5 To Cells(2, Columns.Count).End(xlToLeft).Column
        If Cells(2, j) = [b1] Then
            For i = 3 To 6
                Cells(i, j) = Cells(i, 2)
            Next
        End If
    Next
    For j = 13 To Cells(2, Columns.Count).End(xlToLeft).Column
        If Cells(2, j) = [b1] Then
            For i = 3 To 6
                Cells(i, j) = Cells(i, 2)
            Next
        End If
    Next
End Sub
На второй строчке выдает ошибку "Ошибка времени выполнения Basic. Объектная переменная не установлена"

bigor

Поддержать наш форум можно здесь

sokol92

У меня во второй строке стартового макроса в Calc ошибка не возникает.
Разумеется, в начале модуля LO Basic должна быть строка:
Option VbaSupport 1
Владимир.

kroush

Цитата: sokol92 от 26 ноября 2023, 15:53У меня во второй строке стартового макроса в Calc ошибка не возникает.
Разумеется, в начале модуля LO Basic должна быть строка:
Option VbaSupport 1

Спасибо большое, все работает.

kroush

#4
Все равно решил переписать под libre.
Sub pps()
Dim doc as Object
       dim sheet as OBJECT
       dim strokaC as Object
       dim stroka as object
       doc  =  thiscomponent
       sheet = ThisComponent.CurrentController.ActiveSheet
                   for column = 4 to 13
                 Data = sheet.getCellByPosition(column,1).value
                 oData = sheet.getCellByPosition(1,0).value
                      if data = odata then
                      'If  sheet.getCellByPosition(column,1) = sheet.getCellByPosition(1,0) Then
                            for stroki = 2 to 5
                                dannie= sheet.getCellByPosition(1,stroki).value
                                stroka= sheet.getCellByPosition(1,stroki)
                                strokaC =  sheet.getCellByPosition(column,stroki)
                               Doc.sheets(2).getCellByPosition(column,stroki).setValue(dannie)
                          '    sheet.copyRange (strokaC.CellAddress, stroka.RangeAddress)
                           '     strokaC=stroka
                                next
                         end if
                next   
End Sub
Затык встал в формуле Doc.sheets(2).getCellByPosition(6,5).setValue(stroka). Как использовать активный лист (а не ручками тыкать (листов будет 8).
Если использовать  sheet.copyRange (strokaC.CellAddress, stroka.RangeAddress) то копируется вместе с формулой, а мне надо только вычисление формулы.

Разобрался. если использовать код то все работает . doc = sheet.getCellByPosition(column,stroki)
doc.setValue(dannie)
Объясните пожалуйста разницу между выше и doc.sheet.getCellByPosition(column,stroki).setValue(dannie)

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

bigor

kroush
Цитата: kroush от 26 ноября 2023, 22:41между выше и doc.sheet.getCellByPosition(column,stroki).setValue(dannie)
выше это оно:
Цитата: kroush от 26 ноября 2023, 22:41Doc.sheets(2).getCellByPosition(6,5).setValue(stroka)
? ну тогда в нем, вы явно задаете третий лист  - Sheets(2), а в том что ниже у вас и выше у меня :) вы используете sheet,  который ранее определен как активный лист
Цитата: kroush от 26 ноября 2023, 22:41sheet = ThisComponent.CurrentController.ActiveSheet
Цитата: kroush от 26 ноября 2023, 22:41теперь хочу чтобы копировал лист из закрытого документа
можно через get(set)DataArray или get(set)Transferable, правда документ все равно придется открывать, но можно в "невидимом" режиме.
 

Поддержать наш форум можно здесь

sokol92

#6
Цитата: bigor от 27 ноября 2023, 08:52можно через get(set)DataArray или get(set)Transferable, правда документ все равно придется открывать, но можно в "невидимом" режиме.
 
И еще importSheet.
Владимир.

kroush

#7
Спасибо за помощь  :beer:  Пишем потихоньку. Все что задумывалось все получилось. Теперь в планах немного усовершенствовать код, ну или усовершенствовать формулы на листе
Есть функция: =СУММЕСЛИ($Данные.A$2:A$10;"бакалея*";$Данные.B$2:B$10), которая берет с определенного листа нужные данные и при совпадении суммирует. На этот лист таблица выгружается из другого файла (Благодаря вашей помощи это делает макрос). Так вот, можно ли чтобы эта функция сравнивала определенную ячейку с определённой информацией, если нет совпадения переходила к следующей и так несколько раз. И уже потом применялась сама. Что типа: Если ячейка А3 = "ППС" тогда СУММЕСЛИ($Данные.A$2:A$10;"бакалея*";$Данные.из того столбца где условие выполнено), иначе проверяем следующую ячейку и так пока не найдем нужную.
Если так не вариант то можно попробовать через макрос.
Есть идея как это провернуть в макросе. Пример:
sub primer ()
  sheet = ThisComponent.CurrentController.ActiveSheet
   sheets = ThisComponent.Sheets

  str1=sheets (3).getCellByPosition(0,0).value
  str2=sheets (3).getCellByPosition(0,1).value
    str3=sum(str1,str2)
    str4=sheets (3).getCellByPosition(0,2)
    str4.setvalue(str3)
End sub
Но дело в том, что он не знает функцию sum или sumif (пробовал и summ). А мне надо при совпадении ячейки просуммировать определенный столбец.

З.Ы. Строго не судите, это вообще мой первый в жизни макрос и опыт программирования чего-то работающего в этой сфере.

economist

Во всех случаях, когда можно обойтись форумулами/функциями, а не макросами - нужно обходиться формулами. Их нужно знать хорошо.

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

Во-вторых, Функции СУММЕСЛИ() ВПР() и др. хорошо оптимизированы и работают условно "в 4 раза быстрее" таких же макросов с циклами. Со временем проявится "темная сторона" макросов: когда их много/сложны - Calc начнет падать.

В функцию СУММЕСЛИ() можно вложить условия, которые тоже м.б. вложенными в И(Условие1;Условие2...). Грубо говоря, нет такого отчета, который нельзя было бы построить с использованием одной лишь функции СУММЕСЛИ() и И/ИЛИ/НЕ. Но важно вот что: не упустите момент когда вы начнете делать "отчет", а не просто вспомогательные инфо-строки на форме "ввода" данных. Подходы к "отчету" и "форме ввода" - разные. Эти формы "виляют собакой" - т.е. задают оптимальный способ хранения самих исходных данных, тот, из которого легче всего получить и отчет, и форму ввода с некими расчетными значениями-помогашками. Иногда нужно просто поменять местами столбцы в основной таблице - и все становится проще. Если строк больше 10 тыс. - Calc будет подтупливать, нужно думать о базе данных. Эти БД со своим языком запросов SQL не зря главенствуют в данных уже 50 лет. Там как раз без разницы порядок столбцов - на скорость выборки не влияет их порядок. И даже число строк не важно - 100 или миллиард, скорость выборки за счет многих ухищрений примерно одинакова (мгновенна).

Проектируя таблицы важно не забывать про уник. идентификаторы (артикулы, коды классификатора ОКП или в крайнем случае № п/п) в каждой табличке, предусмотреть средства борьбы с дубликатами (функции МОДА() для числовых кодов или СЧЕТЕСЛИ() для слов бакалея, Бакалея, БАКАЛЕЯ) и авто-сортировку "справочников". Вот только после того как сделано все это с удобным форматом хранения сырых данных, справочники и расчеты формулами, если их не хватило - добавляем макросы. Функции sum(), sumif() vlookup(), а также запись в ячейки формул текстом вида "=""СУММ(...)"""- доступны и в макросе. Но это верный признак забегания вперед (исключение - обработка чужого документа).
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

bigor

Цитата: kroush от  3 декабря 2023, 23:47А мне надо при совпадении ячейки просуммировать определенный столбец.
я плохо понимаю, что вы хотите, если возможно приложите пример. Из того, что сейчас я понял вам достаточно =sumproduct()
Поддержать наш форум можно здесь

kroush

К сожалению то что я делаю нет в программе которой мы работаем и у нас нет доступа к базам данных. Все делается на основе выгружаемого отчета из программы (с которой работаем) с накоплением данных для анализа.
Да и доступ на работе есть только к корпоративным сайтам.
В примере маленькая часть таблицы для понимания.

В примере значения из ячейки B3-B6 в зависимости от установленной даты, копируются в столбцы Е2-W2 при совпадении даты (это все делает макрос, для исключения ошибок со стороны пользователей). Значения в ячейках высчитываются по формуле =СУММЕСЛИ($Данные.A$2:A$10;"бакалея*";$Данные.B$2:B$10). А вот в лист с данными мы как раз и копируем из выгруженного отчета и он меняется в зависимости от выгрузки из нашей программы.
Первый раз мы выгружаем данные ППС, второй - МД, третий другие значения.
Выгружаемый отчет из нашей программы позволяет за один раз выгрузить всю информация, но проблема в том, что столбы ППС, МД и другие динамические. Т.е. если в этот день по этим столбцам нет данных то Наш отчет эти столбцы просто не формирует.
И чтобы не делать Наш отчет несколько раз ( в среднем формируется по 3-5 мин каждый), можно за 3-5 мин сформировать один.
Не могу придумать как можно реализовать: Если ячейка B1 из листа данные = "ППС" тогда СУММЕСЛИ($Данные.A$2:A$10;"бакалея*";$Данные.B$2:B$10), иначе проверяем следующую ячейку и так пока не найдем нужную и выполним СУММ именно этого столбца. Именно формулой. И если это не возможно, то попробовать через макрос.
А макрос, как написал выше не понимает функций. Была идея через SetFormyla или FormylaLocal, а затем копировать значение и вставлять в эту же ячейку (но больше похоже на костыль)

P.S. хотелось бы конечно функцией (они работают быстрее) хотя загружаемый отчет менее 500 строк, а то бывает и по 50 или даже меньше. А если формулой не возможно, то тогда все расчеты спрятать в макрос и оттуда уже необходимое вставлять.

bigor

Немного стал понимать, формула в B3 листа ноябрь и протянуть вниз =SUMPRODUCT((Данные.$B$1:$J$1="ППС")*(ISNUMBER(SEARCH(A3;Данные.$A$2:$A$10)))*(Данные.$B$2:$J$10))
Поддержать наш форум можно здесь

kroush

Спасибо большое, почти работает. Но  столбцы d1:j1 не постоянны(если нет какого параметра наш отчёт его не выгружает. И соответвественно в массив попадает текст и происходит ошибка #знач!

bigor

Цитата: kroush от  5 декабря 2023, 10:57в массив попадает текст
не должен текст в массив попадать, а вот лишняя звездочка возможно мешает (после бакалея)
Поддержать наш форум можно здесь

kroush

Я понимаю, что текст в массив не должен попадать.
Спасибо за звёздочку. Подправил.
Вся загвоздка что столбы с данными не постоянны. Например 03.12 выгружаем отчет в нем будут содержаться столбцы E,F,G,H и все они содержат только числовые данные. А вот выгрузм 04.12 и останется столбец только Е ( т. к. За 04.12 не было никаких данных по остальным), соответственно столбец с текстом К встанет на место столбца Н и текст попадёт в массив. Можно ли это как нибудь включить в проверку?