让我们根据您对提议的用户界面的描述来重新制定任务。
在单元格中,您需要输入步长为 0.01 的数值。此值的最小和最大限制在输入单元格右侧的两个单元格(在同一行中)中指示。为了便于输入,最好使用合适的控件来用鼠标选择值。但是,也允许从键盘手动输入值。
首先,如果没有宏编程,这个任务就无法解决。
首先,让我们学习如何区分宏应该工作的单元格与工作表上的所有其他单元格。
最简单的方法是创建自定义单元格样式并将其应用于工作表上所需的单元格。 “cell”对象有一个.CellStyle 属性,我们可以通过它轻松识别所需的单元格。让我们将样式命名为“setValue”,并在宏的开头输入描述
Const STYLENAME_OF_FIELD = "setValue"
现在是一个简单的条件
If oCell.CellStyle = STYLENAME_OF_FIELD Then
将阻止执行其他单元格的代码。
好的,现在让我们回答您在标题中提出的主要问题:如何将输入限制为指定值。由于限制会动态变化,因此不要使用内置的 Data-Validity-Criteria 机制。编写如下所示的子例程会更容易:
Sub onValueChanged(oEvent As Variant)
Dim nColumn As Long, nRow As Long
Dim minValue As Double, maxValue As Double, newValue As Double
Dim oSheet As Variant
Rem Is this Event frome single cell?
If oEvent.SupportsService("com.sun.star.sheet.SheetCell") Then
Rem Does this cell have our predefined style?
If oEvent.CellStyle = STYLENAME_OF_FIELD Then
Rem To find out the contents of neighboring cells,
Rem you need to understand where this cell is located in our spreadsheet
nRow = oEvent.getCellAddress().Row
nColumn = oEvent.getCellAddress().Column
oSheet = oEvent.getSpreadsheet()
Rem Now you get the limits easily:
minValue = oSheet.getCellByPosition(nColumn+1, nRow).getValue()
maxValue = oSheet.getCellByPosition(nColumn+2, nRow).getValue()
Rem The current value of the cell is not available for any event via .getValue()
newValue = Val(Replace(oEvent.getFormula(),",","."))
Rem If the current value is out of range, return it back
newValue = IIf (newValue > maxValue, maxValue, newValue)
newValue = IIf (newValue < minValue, minValue, newValue)
Rem And write this value back into the cell
If newValue <> oEvent.getValue() Then oEvent.setValue(newValue)
EndIf
EndIf
End Sub
(这会起作用,但我必须警告你 - 这段代码还远未完成!该事件可能不是由一个单元格中的更改触发,而是由整个单元格范围内的更改触发。甚至是几个不同的范围。此外,当前单元格可能出现在行尾,而其右侧根本没有单元格。这段代码不处理这些情况)
现在关于可以信任的使用鼠标输入数据的控件。
您可以尝试使用滚动条。它非常适合输入范围不是很大的整数值。但这不太适合您的任务,用于处理小数值。 (您询问滚动条值是如何传递到单元格的。这不是通过事件处理,而是通过链接单元格,在“数据”选项卡上设置)
一组几个按钮组合成一个组可能对您的任务很方便。将每个按钮的 Tag 属性设置为某个值,然后就可以通过一个宏来控制它们了:
Sub onBtnClick(Optional oEvent As Variant)
Rem Each button in group work with this Sub
Dim oCell As Variant
Dim oModel As Variant
Dim DeltaFromTag As Double
oModel = oEvent.Source.getModel()
DeltaFromTag = Val(oModel.Tag)
oCell = getActiveCell()
oCell.setValue(oCell.getValue() + DeltaFromTag)
onValueChanged(oCell)
End Sub
注意最后一行。使用宏更改单元格值不会引发 Content Changed 事件。因此,我们自己调用所需的代码。
将此子例程分配给每个按钮的事件处理程序 Action Execute
其他几个宏控制一组按钮的显示——代码可见in this file。调用主要的 - onChngSelected() - 分配给工作表事件选择更改。
分配工作表事件处理程序很简单:从菜单中选择工作表事件,或者只需右键单击工作表的选项卡