Запрет изменения содержимого ячейки

Автор Kopusha, 12 октября 2011, 16:31

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

Kopusha

Добрый день!

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

JohnSUN

Гм... Вообще-то это делается через Формат-Ячейки (Ctrl+1) и на вкладке Защита ячейки установить нужные флажки. После этого - Сервис-Защитить документ-Лист
Но почему этот вопрос в бэйсике? Защиту нужно устанавливать динамически?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Kopusha

#2
Если бы всё было так просто.
Есть документ с данными, последняя строка содержит хитрую формулу, которая считает сумму по различным критериям. Пользователи всегда её удаляют, поэтому надо защитить эту ячейку. Проблема в том, что количество строк в документе изменяется. Туда надо добавлять или удалять оттуда строки. Если сделать эту ячейку защищенной, то удаление или добавление строк будет приводить к ошибке.
Тема по ссылке про другое.

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

Kopusha

По ссылке нашёл такую штуку
Sub AddChartDataListener()
oCell1 = ThisComponent.getSheets().getByIndex(0).getCellRangeByName("Form")
oListener = CreateUnoListener("MyApp_", "com.sun.star.chart.XChartDataChangeEventListener")
oCell1.addChartDataChangeEventListener(oListener)
End Sub

Sub MyApp_chartDataChanged(oEvent)
dCell = ThisComponent.getSheets().getByIndex(0).getCellRangeByName("Form")
MsgBox dCell.String 'dCell.Value
End Sub

Но тут вывод нового значения после изменения. А мне надо, чтобы отменить это изменение. Надеюсь понятно выражаюсь  :)

JohnSUN

#4
Слушай, а может попробовать другой подход?
Ну, как вариант:
1. Все-таки защитить лист от изменений. Жестко. С каким-нибудь жутким паролем. Пользователь при этом потеряет возможность удалить строку с хитрым суммированием. При этом потеряется возможность удалять-добавлять и другие строки. Но вот тут-то макросом можно компенсировать эту потерю: две кнопки с картинками "плюс" и "минус", каждая из которых будет запускать свой макрос - или вставка новой строки перед строкой с неудаляемой формулой (если там еще нет пустой строки), или удаление текущей строки (если текущая строка в диапазоне, из которого можно удалять).
Преимущества: лишних строк всегда будет не больше одной и хитрое суммирование всегда будет на месте; макрос запускается не по каждому событию, а только по нажатиям кнопок.
Недостаток: Если таблица высокая, а кнопки для вставки-удаления строк разместить вверху, то работать будет не очень удобно - кнопки будут уползать за край окна. Впрочем, если закрепить верх таблицы вместе с кнопками на экране (Окно - Фиксировать), то проблема отпадает.

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

PS. В том макросе, который ты процитировал, используется слушатель события "изменились данные для диаграммы". Для запрета каких-либо действий лучше использовать слушатель-"держиморду" (XVetoableChangeListener). Разница не очень велика, но вроде как этот самый "VetoableChange" предназначен именно для наложения вето на запрещенные изменения....
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

RFJ

Цитата: Kopusha от 13 октября 2011, 07:38последняя строка содержит хитрую формулу
Сделать ее первой.
Делать строку с формулой последней идет от бумажной бухгалтерии.
В электронной вычисления надо делать в первой.

RFJ

Цитата: Kopusha от 13 октября 2011, 07:38Пользователи всегда её удаляют
Значит, она никому из пользователей не нужна.
Тогда вынести ее на другой лист.

Kopusha

Цитата: RFJ от 13 октября 2011, 10:52
Значит, она никому из пользователей не нужна.
Тогда вынести ее на другой лист.
Если нет желания помочь, прошу не постить.
Удаляют, потому что у них есть руки, которые только и ищут что бы такое удалить важное, чтобы потом можно было кого-нить обвинить в пропаже важных данных. Формула есть на отдельном листе, но каждый раз приходится править диапазон ячеек, из которого её считать, да и сам факт, что приходится её приходить и копипастить, если есть (я думаю) возможность просто запретить её удалять.
Итог внизу - ну уж извините, директор привык, чтобы в распечатке строка итогов была внизу.

Kopusha

VetoableChange почему-то роняет LibreOffice3.4.3
Sub AddVetoChangeListener()
oCell1 = ThisComponent.getSheets().getByIndex(0).getCellRangeByName("Form")
oListener = CreateUnoListener("MyApp_", "com.sun.star.chart.XVetoableChangeListener")
oCell1.addChartDataChangeEventListener(oListener)
End Sub

вроде срабатывает нормально, но при изменении значения в ячейке (в моем случае меняю одно из значений, входящих в формулу, т.е. меняется само значение ячейки, а не формула в нём) LO без объяснений падает. Может как не так использую?
функция MyApp_VetoableChange(oEvent) пустая, в ней ничего не писал.

JohnSUN

#9
Там фишка в чем... Для регистрации XVetoableChangeListener нужно использовать не addChartDataChangeEventListener, а специальный addVetoableChangeListener

А можешь саму формулу хитрого суммирования показать? Может быть удастся её совместными усилиями переписать так, чтобы она не зависела от конкретного диапазона ячеек?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

JohnSUN

Чуть подробнее о слушателях и событиях.

Сам Event, который передается в обработчик, в наш макрос, который что-то должен сделать по событию - это структура с несколькими полями.
В случае ChartDataChange в эту структуру входят Type, StartColumn, EndColumn, StartRow и EndRow
А в случае VetoableChangeListener у Event'а структура уже другая, PropertyChangeEvent. Там тоже пять полей, но это уже PropertyName, Further,  PropertyHandle, OldValue и NewValue.
Поэтому офис и путается, когда одному регистратору подсовывают другого слушателя.
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

RFJ

#11
Нужен Listener, который следил бы за добавлением/удалением строк/столбцов.
Нужен, если попытаются удалить строку с формулой!
И использовать "именованные" диапазоны.

JohnSUN

А если формулу сотрут обычным Delete или Backspace? Или просто перезапишут на что-то другое?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

RFJ

#13
Всё работает на
"com.sun.star.chart.XChartDataChangeEventListener"
если каждый раз снова вставлять формулу
myf= "=SUM(summa)"
oCell=oSheet.getCellRangeByName("formula")
oCell.setFormula(myf)


Нужен Listener, который следил бы за добавлением/удалением строк/столбцов.
Нужен, если попытаются удалить строку с формулой!

PS. В общем, всё весьма долго и нудно.

Kopusha

а есть в OO подобие Wordовский variables, т.е. переменные, которые хранятся в самом документе. Типа таких глобальных переменных. Чтобы, допустим, хранить в ней текущее значение формулы. Т.е. при закрытии документа сохраняем туда формулу. Потом XChartDataChangeEventListener при срабатывании копирует её в нужную ячейку.

при регистрации XVetoableChangeListener ступил :)
Регистрация XVetoableChangeListener требует указания параметра PropertyName типа String за которым он будет следить. Что мне туда указать, чтобы он следил и запрещал изменение/удаление формулы?

Извиняюсь, но в OOBasic не шарю совсем, поэтому могу тупить :)