【问题标题】:LibreOffice Calc: Stepping through a range of values between limits in given cellsLibreOffice Calc:在给定单元格的限制之间逐步执行一系列值
【发布时间】:2021-11-10 07:16:33
【问题描述】:

在 LibreOffice Calc 中,我正在计算侵蚀和防洪。我有一组这样的数据:

这是在第二张表中,用于我的数据和其他最终用户不需要看到的“丑陋”的东西。在第一张纸上,我使用 Data->Validity->Cell Range 来显示表面类型的列表,以便我们可以选择我们正在使用的表面类型。从那里,我使用 VLOOKUP 选择低系数和高系数以进入接下来的两个单元格。所以我有这个:

我选择了 Gravel,因此通过从我的表中读取数据,它为我提供了可用于系数的高低值。

接下来,为了简单起见,我想要一个名为“表面系数”的输入字段。我想使用微调器或滑块之类的东西,这样我们就可以快速地在该行的第 4 列和第 5 列中的高数和低数之间选择一个值。例如,在这里,滑块/滚动/微调器的下限为 0.5,上限为 0.7。如果可能,它将以 0.01 的间隔递增。如果我将表面类型更改为“砾石”,那么滑块/滚动/旋转器/任何东西都会在 0.50 的低点和 0.70 的高点之间进行选择。

我发现了如何在电子表格中将滚动条作为表单控件并将值链接到单元格。我知道我可以为该滚动条指定低值和高值,但只能通过指定实际数字。它不会让我将单元格指定为下限和上限。

我可以使用不同类型的控件。我基本上想要一个控件,它可以让我以我设置的增量在低范围和高范围(在单元格中指定,而不是直接数字)之间步进。

有没有办法在滚动条或其他控件中指定单元格用于上下限,让我做我想做的事?

【问题讨论】:

  • 是的,有这样的方法。 this question 中讨论了非常相似的事情。也许在那里你会找到现成的解决方案。
  • @JohnSUN:我明白你在说什么,但我遇到的最大问题是我认为无法解决的问题是我需要使用值设置上下限在单元格中,而不是数值,并且在“控件属性”框中,这些限制的输入只允许数字,而不是单元格值。
  • 这不是很困难:您只需要在宏中添加几行 - 读取两个相对于当前单元格(最小值和最大值)偏移的值,并且当单元格值发生变化时,分配它MAX(MIN(选定值;最大值);最小值)。现在我只是稍微修改最后一条评论中引用的代码。
  • 也许this file 会帮助您解决问题。
  • @JohnSUN:看起来它会做到的。我仍在检查代码——现在有点被猛烈抨击,所以直到今晚晚些时候我才能仔细观察它。你想把它写下来作为答案,以便我选择它吗?它与您的其他示例完全不同,我认为值得将其视为一个不同的问题,以便您可以在此处获得对此的完整答案(包括单元格引用)。

标签: libreoffice calc


【解决方案1】:

让我们根据您对提议的用户界面的描述来重新制定任务。

在单元格中,您需要输入步长为 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() - 分配给工作表事件选择更改。

分配工作表事件处理程序很简单:从菜单中选择工作表事件,或者只需右键单击工作表的选项卡

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多