массив константа

Автор Alex16, 15 ноября 2016, 10:47

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

economist

Мне кажется это тот самый случай, когда проще обойтись
без программирования на StarBasic, - формулами решить вопрос.  
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

rami

Цитата: economist от 15 ноября 2016, 16:43
Мне кажется это тот самый случай, когда проще обойтись
без программирования на StarBasic, - формулами решить вопрос.
Alex16 пока ещё не знает сам, какой у него случай, он просто с макросами играется ;D — это хорошо, будет знать, что вариантов много и надо выбирать лучший.

JohnSUN

Цитата: Alex16 от 15 ноября 2016, 13:36Цитата: JohnSUN от Сегодня в 13:14
А под заголовками я вообще-то имел в виду не A-B-C, а "Товар", "Цена", "Дата поступления", "Дата списания" и т.п.
Ай, нет.... Есть номера(или буквы) колонок, и кол-во строк.
Нет, не греет... "Ну, я так не играю..." (с) Карлсон
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

#18
Const StrColumns = "A, B, D"

Sub LoadData1222
StrColumnsArr=split(StrColumns, ",")
for N = LBound(StrColumnsArr) to UBound(StrColumnsArr)
  for K = 10 to 12
   Addr = StrColumnsArr(N) & K
   'Print Addr
   Print Addr & " - " & ThisComponent.Sheets(0).getCellRangeByName(Addr).GetString
   'ThisComponent.Sheets(1).getCellRangeByName(Addr).SetString(ThisComponent.Sheets(0).getCellRangeByName(Addr).GetString)
  next K
Next N
End Sub


На второй итерации первого цикла, т.е. когда Addr становится B10 вылазит ошибка:
"Ошибка времени выполнения BASIC.
Вызвано исключение
Type: com.sun.star.uno.RuntimeException
Message: ."

ЦитироватьМне кажется это тот самый случай, когда проще обойтись
без программирования на StarBasic, - формулами решить вопрос.  
На самом деле в коде выше будет вместо строчки:
ThisComponent.Sheets(1).getCellRangeByName(Addr).SetString(ThisComponent.Sheets(0).getCellRangeByName(Addr).GetString)
примерно вот такая:
ThisComponent.Sheets(1).getCellByPosition(Indx * 6 + N, R - StartColRow).SetString(ThisComponent.Sheets(0).getCellByPosition(C, R).GetString)
Ну т.е. это пока из экспериментов с getCellByPosition. Но по сути если заработает код в начале этого сообщения, я смогу его переделать к нужному мне.
В общем-то уже можно сделать с преобразованием типов, но хотелось бы пограмотнее....
Лет 10 назад было хобби программирования на Делфи.... но здесь как-то все не так. И редактор кода не помогает, как в IDE Delphi (или даже в VBA MS Excel) :) это когда поставишь точку и вываливается список свойств-методов.... А тут в мозгу я так понял нужно все хранить)

rami

Цитата: Alex16 от 15 ноября 2016, 15:02На второй итерации первого цикла, т.е. когда Addr становится B10 вылазит ошибка:
"Ошибка времени выполнения BASIC.
В строке:Const StrColumns = "A, B, D" убрать пробелы перед B иD

Alex16

Цитата: rami от 15 ноября 2016, 15:12убрать пробелы перед B иD
Блин, дело было не в бабине.... Этж не массив, а обычная строка)
:) Спасибо.
В общем-то работает. Но ведь тут тоже есть моменты с преобразованием например вот тут: Addr = StrColumnsArr(N) & K
или libreoffice basic это как-то по своему на низком уровне делает?

Хотя в любом случае пока остановлюсь на вариантах, предложенных в этой ветке. Ибо других у меня нет( Благодарю за помощь.
Отдельная благодарность rami за огромное терпение и желание всегда помочь!

rami

Возможно подойдёт не перебор ячеек в цикле, а копирование/перемещение диапазонов (отдельных столбцов):
Sub main
oSheet0=ThisComponent.Sheets(0)
oSheet1=ThisComponent.Sheets(1)
oRangeAddress=oSheet0.getCellRangeByName("B4:B25").RangeAddress 'диапазон копирования на "Лист1"
oCellAddress=oSheet1.getCellRangeByName("B4").CellAddress       'место вставки на "Лист2"
oSheet1.copyRange(oCellAddress,oRangeAddress)
End Sub

Диапазон B4:B25 копируется с первого листа на второй. Буквенные адреса можно заменить на числовые. Отдельные диапазоны (а не отдельные ячейки) можно перебирать в цикле.

Alex16

#22
Цитата: rami от 15 ноября 2016, 15:22Возможно подойдёт не перебор ячеек в цикле, а копирование/перемещение диапазонов (отдельных столбцов):
Вот, это уже горячо. Наверное это будет как раз то, что доктор прописал. Огромнейшее Спасибо!
Нужен будет только цикл по колонкам сделать, а по строкам цикл отпал. Но эксперимент продолжу завтра...

JohnSUN

Цитата: rami от 15 ноября 2016, 17:12
В строке:Const StrColumns = "A, B, D" убрать пробелы перед B иD
...или обжать эти буквы через Trim()
Addr = Trim(StrColumnsArr(N)) & KА по-хорошему - не туда ты сейчас роешь, ой, не туда...
Видимо, сказываются навыки навязанные VBA.
Нужно помнить, что объектные модели этих электронных книг, не смотря на очень схожий вид, разные.
Если Эксель любит, когда ему каждую ячеечку оближут по несколько раз (считать значение-записать значение-посмотреть, что записалось-еще раз переписать), то в ODF эта операция - обращение к одной ячейке - сопоставима по времени с чтением всего листа. То есть, перебирая почти полтысячи ячеек (колонки "A, C, F, G, J" в строках с 10 по 100) ты попадёшь в жуткие тормоза.
Здесь, в LiO, это делается иначе.
Начало, в принципе правильное - получить в переменную все листы книги
oSheets = ThisComponent.getSheets()
С помощью этого объекта можно получать отдельные листы
oSheet1 = oSheets.getByIndex(0)
или
oSheet2 = oSheets.getByName("Отчет")

Имея лист можно уже определить диапазон ячеек на нём
oCellRange = oSheet1.getCellRangeByPosition(1, 0, 137, nEndRow)
или с помощью курсора одним движением охватить весь диапазон с непустыми ячейками
oFullRange = oSheet1.createCursor()
oFullRange.gotoEndOfUsedArea(True)

У диапазона есть методы "массового чтения" - getData (числовые данные), getDataArray (данные любого типа - и числа, и строки), getFormulaArray... Эти методы возвращают "массив массивов" - массив строк, в котором каждый элемент это отдельный массив ячеек в строке.
Получив данные в массив очень быстро обрабатываешь их в любом порядке и обратным методом (например, setDataArray) пишешь в нужное место (хоть поверх старых данных, хоть в другой лист)
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

Цитата: JohnSUN от 15 ноября 2016, 15:46Если Эксель любит, когда ему каждую ячеечку оближут по несколько раз (считать значение-записать значение-посмотреть, что записалось-еще раз переписать), то в ODF эта операция - обращение к одной ячейке - сопоставима по времени с чтением всего листа. То есть, перебирая почти полтысячи ячеек (колонки "A, C, F, G, J" в строках с 10 по 100) ты попадёшь в жуткие тормоза.
Мне бы очень хотелось из этого сделать вывод для себя, но пока ничего в голову не приходит как нужно создавать переменные, наподобие как
oDoc = ThisComponent
oSheet = oDoc.Sheets(0)
oCell = oSheet.... и т.д.
и затем работать именно с этими переменными oCell.CellBackColor = ...
а не ThisComponent.oDoc.Sheets(0).getcellbyposition().CellBackColor = ...

или все таки разговор о диапазонах. Т.е. работать не с ячейками (хоть в переменной "oCell" хоть напрямую "ThisComponent.oDoc.Sheets(0).getcellbyposition()"), а с областями?
Т.е. то что предложил rami последним будет самым оптимальным вариантом?

JohnSUN

Нет-нет, я не говорил, что .getCellByPosition() или .getCellRangeByName() плохие методы!
Ими безусловно можно и нужно пользоваться. Это когда речь идет о двух-трех, пусть о десятке перезаписей.
И для твоего примера с фоном ячейки это пригодно (хотя для работы с цветами лучше использовать присвоение имени стиля)
Но для обработки больших таблиц лучше использовать другой подход.


Вот, например, возьми приложенный файл и выполни compareTest
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

Цитата: JohnSUN от 16 ноября 2016, 13:03Вот, например, возьми приложенный файл и выполни compareTest
Спасибо. Очень для меня познавательно.
"Массив выполнялся 105 отсчетов
Ячейки выполнялись 5958 отсчетов"
Я увидел применение GetSystemTicks() и у меня возник еще вопрос(не по GetSystemTicks, чуть другого направления), но с ним попозже и в новой теме, а сейчас пока разберусь с данной темой.