Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

22 Январь 2022, 19:58 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: Автоматическое копирование формул при добавлении строки  (Прочитано 1867 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ftryrjyh
Новичок
*
Offline Offline

Сообщений: 1


« Стартовое сообщение: 7 Май 2021, 18:40 »

LibreOffice 7.1
MacOS 11.2.3

Столбцы таблицы
Дата Значение1 Значение2 Вычисление

Значения в Дате должны идти по порядку. Если надо вставить строку между существующих, то в новой строке нет формул, надо копировать перетаскиванием.

Можно ли при добавлении строки автоматически подставлять формулы в новую строку?
В екселе нашел как, в либре нет Грустный

Альтернативой этому могла бы послужить автоматическая сортировка по полю Дата.
Записан
sokol92
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 704


WWW
« Ответ #1: 7 Май 2021, 18:55 »

А как Вы в Excel поступаете?
Записан

Владимир.
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #2: 7 Май 2021, 21:37 »

Выделить диапазон ячеек над и скопировать Ctrl+D. Рекомендуется.
Подставлять макросом при добавлении строки.
В Excel копирование происходи в умной таблице. Здесь их нет.
« Последнее редактирование: 7 Май 2021, 21:43 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
SMihail
Участник
**
Offline Offline

Сообщений: 5


« Ответ #3: 4 Январь 2022, 18:43 »

Я так понял, что на сегодня, способа автоматического копирования формул при добавлении новой строки нет или все таки есть?
Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #4: 4 Январь 2022, 20:43 »

Конечно, нет. Но я добавляю макросом. Однако это решение для хорошо сработанного приложения.

Код приводится для демонстрации. Взято из рабочего приложения. Я не поясняю что и зачем, разве что...
Процедура FillFormulas достаточно демократично решает Вашу задачу, беря формулы из вышестоящей строки. В основе - метод fillAuto. Hardcode практически отсутствует. Ячейки с формулами определяются автоматически. Диапазон данных при добавлении новой записи расширяется автоматически (при заданном параметре).
oDataRange - глобальная переменная, ссылающаяся на диапазон данных (например Вашу таблицу).
Функция GetDataBodyRange() - зд. не приводится - возвращает данные без первой строки с заголовками столбцов. Вы можете её легко заменить парой строчек кода.
Вам осталось только предоставить данные, а я могу нарисовать кнопку "Добавить". Вот и всё. Ну, может ещё перевести на русский несколько сообщений... Я давно уже ничего по-русски не пишу: не удобно, поскольку на других форумах - язык английский. Будет обслуживать любую таблицу, расположенную на листе произвольно. Вы задаете ссылку на именованный диапазон, а код уже работает с ним.

Код написан для реального приложения, поэтому выглядит объемным. В реальности, всю работу делает пара строчек:
    oDataRange.insertCells(oAddress, com.sun.star.sheet.CellInsertMode.DOWN  'вставляет новую строку
    oRange.fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)  'заполняет формулы из вышележащей строки в новую строку
Обратите внимание:
   If oCell.Type = com.sun.star.table.CellContentType.FORMULA Then...
То есть ячейки с формулами определяются без Вашего участия.
Процедура InitObjects инициализирует глобальную переменную при открытии файла.
В примере "YourData" - это имя ваше таблицы, которое Вы определяете сами.


Код:
Const DATA = "YourData"
Global oDataRange As Object


Sub InitObjects()          
''' Called by: Document.Document_OnLoad

On Local Error GoTo HandleErrors
With ThisComponent.NamedRanges
oDataRange = .getByName(DATA).ReferredCells
End With
Exit Sub

HandleErrors:
Msgbox "Error " & Err & " in line " & Erl & ": " & Error _
, MB_ICONSTOP, "macro:InitObjects"
End Sub

Sub AddNew()
''' Add a new record to the DATA range and set 1st cell of the added row active.
''' Called by: cmdAddNew_actionPerformed
''' Calls: ActivateCell, FillFormulas, Utils.GetDataBodyRange()
''' Requires: Document.PASSWORD

On Local Error GoTo HandleErrors
Dim nRow&  'new row index
Dim oSheet As Object, oCell As Object
Dim oAddress As New com.sun.star.table.CellRangeAddress
Dim bProtected As Boolean

oSheet = ThisComponent.CurrentController.ActiveSheet
nRow = oDataRange.RangeAddress.EndRow + 1
With oAddress: .Sheet = oSheet.RangeAddress.Sheet
.StartColumn = oDataRange.RangeAddress.StartColumn
.StartRow = nRow
.EndColumn = oDataRange.RangeAddress.EndColumn
.EndRow = .StartRow
End With
With oSheet
bProtected = .isProtected()
If .isProtected() Then .unprotect(PASSWORD)
.insertCells(oAddress, com.sun.star.sheet.CellInsertMode.DOWN)
Call FillFormulas(oAddress)

With Utils.GetDataBodyRange(oDataRange)
' If the 2nd record was inserted, expand the reference to DATABODY.
If .Rows.Count = 2 Then
ThisComponent.NamedRanges.getByName(DATABODY).Content = .AbsoluteName
End If
End With

If bProtected Then .protect(PASSWORD)
oCell = .getCellByPosition(oDataRange.RangeAddress.StartColumn, nRow)
End With
Call ActivateCell(oCell)
Exit Sub

HandleErrors:
Msgbox "Error " & Err & " in line " & Erl & ": " & Error _
, MB_ICONEXCLAMATION, "macro:AddNew"
End Sub

Sub FillFormulas(oAddress As Object)
''' Transfer only formulas from the record above.
''' If this is the first record, display the message and do nothing.
''' Called by: AddNew

Dim oSheet As Object, oRange As Object, oCell As Object
Dim oPrevDataRow As Object
Dim j%

oSheet = ThisComponent.CurrentController.ActiveSheet
' Get the previous record (must be filled in).
With oAddress: oSheet = ThisComponent.Sheets(.Sheet)
If .StartRow = oDataRange.RangeAddress.StartRow + 1 Then
MsgBox "This is the first record added. If the record contains" _
& " calculated fields, insert the appropriate formulas into them" _
& " using relative (mixed) references. Then these formulas" _
& " will be automatically transferred from the last record" _
& " to the new one when it is added." & Chr(10) _
& Chr(10) & "This message will not appear later.", , "Adding 1st Record"
Exit Sub
End If
oPrevDataRow = oSheet _
.getCellRangeByPosition(.StartColumn, .StartRow - 1, .EndColumn, .StartRow - 1)
End With
' Fill in the formulas in the last record (just added) from the previous one.
For j = 0 To oPrevDataRow.Columns.Count - 1
oCell = oPrevDataRow.getCellByPosition(j, 0)
If oCell.Type = com.sun.star.table.CellContentType.FORMULA Then
With oCell.CellAddress
oRange = oSheet _
.getCellRangeByPosition(.Column, .Row, .Column, .Row + 1)  'block of 2 cells vertically
oRange.fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)  'nSourceCount:=1
End With
End If
Next
End Sub  'FillFormulas

Вообще, в Calc'е работать гораздо сложнее, чем в Excel: квалификация должна быть выше. Однозначно!

На скриншоте три поля справа заполнены процедурой выше.


* Снимок экрана от 2022-01-04 21-09-57.png (67.48 Кб, 1829x236 - просмотрено 4 раз.)
« Последнее редактирование: 4 Январь 2022, 21:29 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
SMihail
Участник
**
Offline Offline

Сообщений: 5


« Ответ #5: 4 Январь 2022, 21:54 »

Спасибо, попробую разобраться!!!
Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #6: 4 Январь 2022, 22:59 »

Там ещё есть вызов (выбирает первую ячейку, но не выделяет её):
Код:
Sub ActivateCell(oCell As Object)
''' Called by: AddNew

Dim oRanges As Object
With ThisComponent
.CurrentController.select(oCell)
oRanges = .createInstance("com.sun.star.sheet.SheetCellRanges")
.CurrentController.select(oRanges)
End With
End Sub  'ActivateCell

Но вы может скинуть мне файл с вашей табличкой. Оставьте только заголовки и одну строку данных и где-то в ней - вычисляемые поля с формулой, использующей относительную/смешанную адресацию. Я подключу процедуру добавления записи с заполнением формул, а Вы посмотрите. Ведь это не разовая работа: таким приёмом придётся пользоваться всегда. У меня все таблицы расширяются кнопкой добавить запись: ведь надо расширять диапазон и переопределять ссылку на него, а вручную это делать утомительно и/или небезопасно.

Замечание. Мой код обрабатывает защиту листа (можно убрать), а также ситуацию с одной записью в именованном диапазоне (при начале ввода данных).
Диапазон данных при добавлении новой записи расширяется автоматически (при заданном параметре).
Referred to the Calc Guide v. 7.1 (p. 477):

EN: Expand references when new columns/rows are inserted specifies whether to expand references when inserting columns or rows adjacent to the reference range. This is only possible if the reference range, where the column or row is inserted, originally spanned at least two cells in the desired direction.

RU: Параметр "Расширять ссылки при вставке новых столбцов/строк" указывает, следует ли расширять ссылки при вставке столбцов или строк, смежных с данным диапазоном. Это возможно только в том случае, если этот диапазон, в который вставлен столбец или строка, изначально охватывает не менее двух ячеек в желаемом направлении.
Код:
   With Utils.GetDataBodyRange(oDataRange)
        ' If the 2nd record was inserted, expand the reference to DATABODY.
        If .Rows.Count = 2 Then
            ThisComponent.NamedRanges.getByName(DATABODY).Content = .AbsoluteName
        End If
    End With

Ну, вот: увидел ссылку на константу DATABODY, о которой не сказал.
Присылайте файл, как я написал.

В моём примере (и в жизни тоже) ситуация усложняется ещё и тем, что использование расширенного фильтра требует наличия строки заголовков полей в именованном диапазоне данных, а в именованный диапазон, который традиционно обрабатывают формулами, наоборот, не надо включать строку заголовков. Это тоже надо учитывать. Отсюда у меня: DATA - данные с заголовками и DATABODY - тело данных без заголовков.
Но я уже не могу представить "серьёзную" таблицу данных без диапазона критериев расширенного фильтра сверху. Значит, заголовки то нужны, то нет.
Откровенно говоря, я не уверен, что Вы вполне понимаете меня... Улыбка
« Последнее редактирование: 4 Январь 2022, 23:32 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #7: 5 Январь 2022, 01:15 »

Вот готовый пример. Пользуйтесь.
В модуле файла задана константа:

Const DATA = "Цветы"

Если Вы измените имя диапазона данных на близкое Вам по тематике, то измените значение константы DATA.
Но сначала изучите пример.
Если Вы перетащите диапазон данных в другое место, то всё будет по-прежнему работать. Решение универсальное. Код модуля является базовым (необходимым и достаточным для решения задачи). Дальше можно наращивать код "под себя".
Защита листа закомментирована (см. процедуру Document_OnLoad).

* Пример-addnew-entry.ods (17.87 Кб - загружено 3 раз.)

* Снимок экрана от 2022-01-05 01-25-48.png (51.74 Кб, 1248x275 - просмотрено 8 раз.)
« Последнее редактирование: 5 Январь 2022, 01:26 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
SMihail
Участник
**
Offline Offline

Сообщений: 5


« Ответ #8: 5 Январь 2022, 09:02 »

ОГРОМНОЕ СПАСИБО!!!    РАЗБИРАЮСЬ!!!
Записан
SMihail
Участник
**
Offline Offline

Сообщений: 5


« Ответ #9: 5 Январь 2022, 12:27 »

Немного разобрался (если так можно сказать), но не получилось поставить макрос на панель задач (при выполнении выдает ошибку). ИЛИ если можно, чтоб кнопка добавления строки автоматическим смещалась вниз (идеальный вариант), при добавлении новой строки.

* Пример из исходного файла с сайта.ods (16.21 Кб - загружено 1 раз.)
Записан
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #10: 5 Январь 2022, 13:06 »

Ну, так переместите кнопку под таблицу: при добавлении новой записи (путём вставки диапазона ячеек) всё, что ниже, будет смещаться вниз на одну строку.
И ещё. Надо ставить защиту листа, чтобы не затереть формулы.
Я в примере кое-что упустил.
Выделите в диапазоне данных все ячейки, кроме строки заголовков столбцов, а также кроме ячеек с формулами, и снимите с них защиту, чтобы можно было вводить данные на защищённом листе.
После этого раскомментируйте строку в процедуре Document_OnLoad, чтобы защита листа всегда устанавливалась при открытии файла. Вы всегда можете снять защиту листа вручную в "текущем сеансе" работы с данными и установить обратно (без пароля).
Добавляемая строка будет копировать формат сверху: одни ячейки без защиты, ячейки с формулами – с зашитой.


UPDATED:
Пример с учётом вышесказанного прилагается...

Файл обновлён повторно. Загрузите ещё раз. Переведено на русский полностью. Исправлены ошибки. Хорошая заготовка для старта.


* Снимок экрана от 2022-01-05 16-27-06.png (43.67 Кб, 836x323 - просмотрено 4 раз.)
* Пример-addnew-entry (1).ods (18.57 Кб - загружено 3 раз.)
« Последнее редактирование: 7 Январь 2022, 23:25 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 845



« Ответ #11: 8 Январь 2022, 00:15 »

Подключил два диапазона данных, расположенных на разных листах, к одной процедуре добавления новой записи.
Оба именованных диапазона объявлены с глобальной областью видимости, но их также можно сделать и локальными (на листах), поскольку процедура добавления записи работает с текущим листом.
См. диалог "Управления именами".

* Пример-addnew-entry (2).ods (19.37 Кб - загружено 5 раз.)
« Последнее редактирование: 8 Январь 2022, 00:31 от eeigor » Записан

Ubuntu 18.04 LTS • LO 7.2.4.1 Community
SMihail
Участник
**
Offline Offline

Сообщений: 5


« Ответ #12: 8 Январь 2022, 16:54 »

 Улыбка Улыбка Улыбка Вы прочитали мои мысли !!! Только хотел это Вам написать, захожу на форум, а вы уже предложили файл. Спасибо!!!
Записан
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!