【问题标题】:Excel: Can cells be made read only without protecting sheet?Excel:可以在不保护工作表的情况下将单元格设为只读吗?
【发布时间】:2021-08-23 22:22:39
【问题描述】:

这是一个小众问题,因为通常 最好保护工作表,但我认为在某些情况下您只需要保护单元格的内容以避免意外通过保护工作表进行编辑和删除而不限制工作表整体的可编辑性,例如创建新过滤器。

我的问题:

我需要通过脚本将 Revit 计划导出到 Excel 电子表格进行编辑,然后再导入到 Revit。这是因为编辑元素,尤其是房间,可能会对我们的项目规模造成负担,并且缺乏直观、快速的方式来排序和替换 Revit 计划中的内容。我创建了一个宏,它将 Excel 文件的完整路径(共享网络驱动器的 UNC 路径)保存到配置文件中,以基本上将计划“链接”到该 Excel 文件。如果在配置文件中找不到excel文件,那么我用OpenFileDialog()CheckFileExists = false创建一个,这样就出现了问题。

如果我创建一个新的 Excel 文件并在保存文件时使用 Microsoft.Office.Interop.Excel 方法 sheet.Protect("password"),导出到新创建的文件的用户需要知道在哪里查看宏以解锁工作表以执行受保护工作表不允许的某些设置。这也将允许他们有目的地或以其他方式更改任何受保护的数据,并损害数据的有效性。更糟糕的是,如果/当我有时间将其变成 Revit 的更高级插件而不是宏时,使用的密码将被隐藏,甚至不允许更值得信赖的高级用户设置工作表。如果我允许用​​户在创建新 Excel 文件时设置密码,那么他们可以随时解锁。

需求:

使用此脚本导出的数据除了包含在 Revit 计划中的内容之外,还包含 Revit 元素的 ElementId,这是将 Excel 数据以 100% 准确度绑定回 Revit 元素所必需的(这是唯一唯一的元素存在时不改变的元素的属性)。如果以在 Excel 文件中创建重复值的方式进行更改,则导入的有效性将被破坏,并且必须进行回滚(此错误越久未被注意到,其严重性就会增加)。

简单地隐藏 ElmentId 列并不能阻止用户取消隐藏它,并且 Protect Sheet 不允许在创建新的 Excel 文件时对工作表进行少量必要的更改。

因此,我需要“防止”意外更改 ElementId 列,但仍允许更改 Protect Sheet 不允许的一小部分功能。

再次,我意识到这是非常利基的需求,通常不是保护数据的理想限制。我也意识到这对保护行的删除没有任何作用,就像保护表一样。也就是说,我的目标是防止将 Excel 中的 ElementId 值更改为另一个有效的 ElementId 值,仅此而已。因此,删除行仅意味着与该特定 ElementId 关联的 Revit 元素在导入数据时不会收到任何形式的更新,因为单元格要么为 null,要么被跳过,要么包含无效的 ElementId,不能关联到现有元素,从而保护所述元素数据的有效性。

【问题讨论】:

  • 所以有一个数据表然后使用可以在vba中设置的“非常隐藏”选项...
  • 此设置是否也可以通过 C# 通过 Interop 库进行设置,或者仅通过内部 VBA 宏进行设置?如果是后者,有没有办法通过互操作库运行/触发它?如果这可以自动化,这将允许我做一些其他的事情来简化处理,但我不熟悉通过互操作直接从/向单元读取/写入之外的任何内容。否则,我想我可以创建一个包含该类型工作表的模板文件,并让我的宏使用它而不是打开一个空白文件。
  • 您是否已经检查了 vba 中非常隐藏的选项?然后你可能会看看你是否可以使用 C#...
  • 是的。我以前用过它,但由于缺乏它,忘记了它。我查看了 Excel.Interop 文档,可见性是一个暴露的属性,它有三个选项,包括xlSheetVeryHidden。不过,你会在这个隐藏的数据表上放什么?我认为 ElementId 会以前所未有的方式使行删除成为一个问题。我知道有一个宏可以防止这种情况发生,但这需要一个 .xlsm 文件,我相信可以禁用该宏...

标签: excel readonly-attribute


【解决方案1】:

对此有两种解决方案。第一个是通过我自己的实验。第二个思路是感谢 Solar Mike 提醒我一个非常有用的功能,但由于缺乏使用(通常不需要它)而我忘记了:非常隐藏的工作表。他似乎建议的途径可能无法完全按照他的预期工作,因为理想情况下,我公司中的任何人都应该可以使用这个 Revit 宏和 Excel 文件组合,但有一种方法可以让它对任何人都有效。以下是解决我的问题的两种方法,希望有类似绑定的其他人由于某种原因无法使用 Protect Sheet 来完成这项工作。


解决方案 1:数据验证

通过设置Allow: CustomFormula: "",我可以触发错误警报功能,并将样式设置为“停止”,这将禁止任何更改。

更好的是,如果我想禁止删除单元格数据,取消选中“忽略空白”框也会在按下单元格上的 Delete 键时出现错误警报。

将其与隐藏列结合使用会混淆通过大量步骤来编辑这些单元格的过程以启用编辑,从而阻止用户费心弄乱单元格内容。

优点:

  • 可以利用输入消息警告用户更改单元格内容的危险
  • 可以使用错误警报彻底阻止数据输入或删除单元格内容
  • 在人们改变价值观之前需要采取额外的步骤,以努力作为一种威慑

缺点:

  • 不能防止以下情况(请进一步阅读以了解详细信息 说明):
    • 删除行(通过在工作簿上使用 this 宏进行偏移 Visual Basic 编辑器)
    • 在只读单元格上复制并粘贴另一个单元格(在一个 宏来消除这个问题)
    • 通过代码或宏更改单元格
  • 需要宏来缓解上述一些限制,可以是 禁用并将数据置于上述问题的风险之中。
  • 需要在 您的数据,这对于那些查看列字母的人来说是显而易见的。
  • 不会阻止人们关闭数据验证,如果有人 认为付出的努力是值得的

删除行:

这个解决方案对我来说并不重要,因为我正在逐行读取 excel 中的数据,使用 ElementId 单元格查找 Revit 元素。如果删除了 Excel 行,则关联的 Revit 元素只是错过了使用该导入获取数据,然后在下一次导出运行时从 schdule 重新添加到 Excel 文件中,只要该元素仍然存在于 Revit 中。但如果您需要维护行数据以避免数据损坏,您可以使用链接宏将其禁用。

代码修改:

至少外部代码;我没有在 Excel 中针对 VBA 宏对此进行测试,但我认为这也是正确的。我认为这是因为数据验证是由用户在界面级别与单元格交互激活的,但是当使用 C# 中的 Microsoft.Office.Interop.Excel 库写入单元格时,您会绕过界面并进行交互直接使用单元格数据,因此不会触发数据验证。我不担心由此引起的安全或验证问题,因为我们的 AEC 公司中很少有人知道如何编码,而且那些确实没有理由与这些文件交互和/或缺乏访问文件夹的权限的人(学科分离)。虽然在大多数情况下并不完美,但这是我能想出的满足我们当前需求的最佳解决方案。

解决方案 2:非常隐藏的工作表

此方法利用了 Excel 的两个特性:

  • 非常隐藏的工作表可见性设置

具体来说,我所指的宏是解决方案 1 的 Con 部分的链接,防止行/列删除。

解决方案是让您的脚本写入两张不同的工作表,一张用于您的整体数据,另一张用于您的唯一标识符。这些内容的编写方式应以这样一种方式进行编码,即在移动到下一张之前,您将在每张表中写入一行,以确保标识符和数据位于同一行并减少将来编辑代码时的错误.

保存新生成的无格式和无过滤器的 Excel 文件时,将标识符表的可见性设置为 xlSheetVeryHidden 或 2。此设置应通过 Interop.Excel 界面作为工作表属性公开。这样,只有可以使用宏的高级用户才能取消隐藏工作表,而且他们甚至知道要查找它。

优点:

  • 确保唯一标识符只有明确告知其存在的人才能访问,即使这样也只有有能力或有工具访问它的人才能访问
  • 通过使用行删除预防宏,标识符将始终与正确的数据配对,只要代码将数据正确写入 Excel 即可
  • 通过消除复制/粘贴风险,比数据验证更安全

缺点:

  • 需要将文件另存为 .xlsm 或启用宏的工作簿,这取决于您公司的安全设置,可能会向不熟悉为什么以这种方式设置文件的人发送危险信号
  • 如果通过安全设置禁用宏,则无法保证数据的有效性,因为行删除预防将被禁用

最后的想法

虽然我更喜欢解决方案 2 及其提供的可用性,但我不能凭良心使用它。我们公司的 OOTB Excel 安装默认禁用宏,一些人认为它们对他们在文件中的任务不是必需的,并且完全忽略了文件顶部的警告。纯粹因为有人不想启用宏而导致数据泄露的风险太大。

我还想补充一点:如果您的情况与我不同,我不会轻易推荐任何一种解决方案。保护工作表是保护单元格数据的最强方式,并且不允许使用现有的排序/过滤功能。我仅将这些作为我的首选解决方案,因为办公室中可能使用我的宏(以及希望未来的插件)的人员的经验和/或知识水平,并且认识到这两种方法都不是完美的防御。

如果有人有任何其他建议,我会很高兴听到他们,如果/当我有更好的工作版本的任一解决方案时,我一定会更新这个答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-20
    • 2016-05-01
    • 1970-01-01
    • 2021-02-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    相关资源
    最近更新 更多