在Excel单元格中创建一个不可编辑的属性,该属性对于c#程序仍然可读

时间:2013-05-10 17:42:15

标签: c# excel

我有一个非常特别的问题。我找了类似的问题,测试了每个人提出的很多解决方案,但没有一个是我需要的。

我的客户需要以excel格式导出数据表。这些数据可以进行排序,修改,重新排列,可以输入新值,某些行可能会消失,其他一些可以占据他们的位置,简而言之,任何事情都可能发生在这些数据上。例如,假设我们导出一个购物清单中显示的商品列表。

ItemID ItemName Price
Fr01   Apple    2.5
Fr02   Orange   4.0
Mt01   Beef     10.0
Mt02   Pork     8.33
Vg01   Carrot   1.25

我的问题是这些数据可以导入到最初创建excel的软件中,以便在“ItemID”的数据库库中更新(或添加)这些值。如果数据在值和类型以及相互关系方面“正确”,我已经进行了验证。

我试着给这个范围命名。问题是当数据被过滤/排序时,名称不遵循内容,它静止在同一位置

original :(范围名称是范围的名称,而不是实际的列)

ItemID ItemName Price || Range Name
Fr01   Apple    2.5   || data_fr01
Fr02   Orange   4.0   || data_fr02
Mt01   Beef     10.0  || data_mt01
Mt02   Pork     8.33  || data_tm02
Vg01   Carrot   1.25  || data_vg01
在ItemName上排序后

ItemID ItemName Price || Range Name
Fr01   Apple    2.5   || data_fr01
Mt01   Beef     10.0  || data_fr02
Vg01   Carrot   1.25  || data_mt01
Mt02   Pork     8.33  || data_tm02
Fr02   Orange   4.0   || data_vg01

如您所见,所有信息都正确遵循,但范围名称除外,因此,当我尝试导入时,我的数据不匹配很多。

我的另一个尝试是使NameRange成为excel中的实际单元格。使用此方法,单元格可以跟随,但可以更改,因此我尝试创建受保护的单元格。遗憾的是,由于这一点,无法插入或删除行。我找到了一个解决方法,其中包括在掩码表中使用名称,但我需要再次同步表单,由于之前提到的相同原因,这是不可靠的。

即使最糟糕的是,我必须同时支持xls(97-2003)和xlsx。

所以我正在寻找一个稳定的解决方法,这将允许我以某种方式存储我的“范围名称”数据在单元格中,使其对Excel用户不可见,但将遵循数据,以便我可以在右侧检索它重新导入数据时放置。

提前致谢。

编辑:

在结局中,我必须能够从C#应用程序编写此属性,然后使用C#读回相同的属性,并且它必须兼容excel文件格式,excel用户无法查看或编辑,但保留其原始值设置,无论发生在表格内的数据,除了删除(我不介意我只是把它放在我写的Apple而不是整个范围的单元格上)

4 个答案:

答案 0 :(得分:1)

好的(我仍然认为在导出时向YMLV添加验证智能更好。)

尝试使用Range.ID字符串属性 - 它在Excel UI中不可编辑或可见,并随单元格移动。如果细胞被删除,它就会消失。如果复制单元格,则会复制ID属性,因此会出现重复。
它是在Excel 2000中引入的,因此可能不适用于Excel 97,但在Excel 2000到Excel 2013的所有文件格式中都应该没问题。
以下是一些示例VBA代码:

Sub putids()
    Dim j As Long
    For j = 1 To 5
        Range("a1").Offset(j - 1, 0).ID = CStr(j)
    Next j
End Sub

Sub getids()
    Dim j As Long
    For j = 1 To 5
        Debug.Print Range("a1").Offset(j - 1, 0).ID
    Next j
End Sub

答案 1 :(得分:0)

我认为您应该使用一些关键列,因为它是您编写的唯一名称,是构成数据行的记录的串联。随你。将其作为最左列,隐藏并锁定它,用户无法显示该列或更改其内容。

然后在另一个工作表中,取相同的值并从A2开始粘贴它们。

现在在B2中输入此公式

=VLOOKUP(<this row's key value>,<Your data array in sheet1>,<column number>,FALSE)

以下是如何固定列/行设置

的示例
=VLOOKUP($A2,BigNamedRange,B$1,FALSE)

现在隐藏该表。

现在,您在第一张工作表中所拥有的区域是您的用户可以过滤/排序/执行任何操作的区域。在您的第二张受控工作表中,您可以按照要查看的顺序获取数据(可以单独更改)来自用户的表格。)

编辑:

点击1:Allow Users TO Edit Ranges并设置您希望用户编辑的范围。 然后,2:,点击Protect Sheet / Protect Workbook(您需要)锁定其他所有内容。

现在,您的用户可以编辑您提供的内容,而不是编辑其他内容 enter image description here

答案 2 :(得分:0)

我看不到命名范围如何帮助您。
您是否考虑过使用before save事件将验证代码添加到工作簿中,以便用户无法保存无效的数据?

或者看看你使用Excel的数据验证规则可以做多少。

否则你必须阅读所有数据并在以后的DB更新时间验证它(这基本上已经太晚了)
据推测,基本验证是iTemID有效 - 您的数据库代码不关心数据的顺序,也可以跳过空行等。

答案 3 :(得分:0)

使用每个人的建议并合并它们。

由于任何简单和正常的解决方案在我们的上下文中都不可行,并且因为唯一可能的属性我们可以尝试将某些内容放入(ID)中并不是持久的,并且事实上我们需要客户端不要意外地破坏该值考虑到任何事情都可能发生并且会发生的事实,因为没有太多的限制,而且由于存在锁定单元的副作用,我们无法在不禁用线操作的情况下锁定纸张的一部分,这是最接近的事情我们能够实现的是将我们的键作为格式化的字符串插入到A列中,其中有一个奇怪的外观公式,允许我们隐藏显示,然后我们隐藏列,使用户无意中无法访问。

=IF(FALSE,"our formatted string","")

由于此隐藏列具有数据,因此在排序时它跟随其行,并且由于我们仅从列B中选择(导致尝试在255个单元格中插入256个值),因此无法复制整行。 )我们可以控制一点“假复制”,即使没有完全消除。

在导入器方面,我们只是通过一个小技巧来回读,将公式与值进行比较(因为值为空,只有公式得到我们的格式化数据)并且有一个小的正则表达式来检索格式化字符串的含义然后执行在实际数据库导入之前的所有验证。

对于其余部分,它将转到用户的培训部分,不要“删除”A列中的数据,而不是搜索它。

再次感谢大家。