Jos*_*wry 5 .net c# excel excel-indirect
以下是从C#动态创建依赖选项列表的一般尝试.当从pick1中选择值'A'时,pick2应该显示来自SecondaryRangeA的值.
此代码几乎可以工作,但它不显示SecondaryRangeA,而是显示文字值"A".
pick2.Validation.Add(XlDVType.xlValidateList,
XlDVAlertStyle.xlValidAlertStop,
XlFormatConditionOperator.xlBetween,
"=INDIRECT(\"A5\")");
Run Code Online (Sandbox Code Playgroud)
当我在导出和修改数据验证后打开excel时,它会显示公式.
=INDIRECT("A5")
Run Code Online (Sandbox Code Playgroud)
如果我在Excel中手动修改公式以排除引号,它按预期工作.
=INDIRECT(A5)
Run Code Online (Sandbox Code Playgroud)
当我将代码修改为以下内容时,我得到一个例外.有任何想法吗?
pick2.Validation.Add(XlDVType.xlValidateList,
XlDVAlertStyle.xlValidAlertStop,
XlFormatConditionOperator.xlBetween,
"=INDIRECT(A5)");
Run Code Online (Sandbox Code Playgroud)
例外:
System.Runtime.InteropServices.COMException was unhandled
ErrorCode=-2146827284
Message=Exception from HRESULT: 0x800A03EC
Source=""
StackTrace:
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at Microsoft.Office.Interop.Excel.Validation.Add(XlDVType Type, Object AlertStyle, Object Operator, Object Formula1, Object Formula2)
at TestExcelValidation.Program.Main(String[] args) in C:\TFS\ExcelInterop\TestExcelValidation\Program.cs:line 44
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Run Code Online (Sandbox Code Playgroud)
完整示例:
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Office.Interop.Excel;
namespace TestExcelValidation
{
class Program
{
static void Main(string[] args)
{
string temporaryPath = Path.GetTempPath();
string temporaryFile = Path.GetTempFileName();
Application appl = new Application();
appl.Visible = true;
Workbook workbook = appl.Workbooks.Open(temporaryFile, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Worksheet worksheet = (Worksheet)workbook.Worksheets.Add();
List<string> primaryList = new List<string>();
primaryList.Add("A");
primaryList.Add("B");
List<string> secondaryListA = new List<string>();
secondaryListA.Add("A1");
secondaryListA.Add("A2");
secondaryListA.Add("A3");
List<string> secondaryListB = new List<string>();
secondaryListB.Add("B1");
secondaryListB.Add("B2");
secondaryListB.Add("B3");
Range primaryRange = AddToExcelNamedRange(worksheet, primaryList, 'A', 1, "PrimaryRange");
Range secondaryRangeA = AddToExcelNamedRange(worksheet, secondaryListA, 'B', 1, "A");
Range secondaryRangeB = AddToExcelNamedRange(worksheet, secondaryListB, 'C', 1, "B");
Range pick1 = worksheet.Range["A5"];
pick1.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, "=PrimaryRange");
Range pick2 = worksheet.Range["A6"];
pick2.Validation.Delete();
pick2.NumberFormat = "Text";
pick2.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, "=INDIRECT(\"A5\")");
pick2.Validation.InCellDropdown = true;
pick2.Validation.IgnoreBlank = true;
}
private static Range AddToExcelNamedRange(Worksheet worksheet, List<string> primaryList, char col, int row, string rangeName)
{
Range range = worksheet.Range[col.ToString() + row.ToString(), col.ToString() + primaryList.Count().ToString()];
range.Name = rangeName;
foreach (string item in primaryList)
{
worksheet.Cells[row, col - 64] = item;
row++;
}
return range;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个解决方法,但我想知道为什么这不起作用。我确信我会再次遇到这个问题。
这是英文答案,只有天知道另外两个在说什么。
通过 C#(或 VBA)在 Excel 中使用验证添加级联下拉列表失败,并出现 COMException 0x800A03EC。
它不起作用的原因是源实际上是空的。
让我向您展示我是如何解决这个问题的。我在 Excel 中注入了一个宏并运行它:
Range pick1 = worksheet.Range["A5"];
pick1.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, "=PrimaryRange");
Range pick2 = worksheet.Range["A6"];
StringBuilder sb = new StringBuilder();
sb.Append("Sub InsertCascadingDropDown()" + Environment.NewLine);
sb.Append(" Range(\"A6\").Select" + Environment.NewLine);
sb.Append(" With Selection.Validation" + Environment.NewLine);
sb.Append(" .Delete" + Environment.NewLine);
sb.Append(" .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= xlBetween, Formula1:=\"=INDIRECT(A5)\"" + Environment.NewLine);
sb.Append(" .IgnoreBlank = True" + Environment.NewLine);
sb.Append(" .InCellDropdown = True" + Environment.NewLine);
sb.Append(" .ShowInput = True" + Environment.NewLine);
sb.Append(" .ShowError = True" + Environment.NewLine);
sb.Append(" End With" + Environment.NewLine);
sb.Append("End Sub" + Environment.NewLine);
//You need to add a COM reference to Microsoft Visual Basic for Applications Extensibility for this to work
var xlmodule = workbook.VBProject.VBComponents.Add(Microsoft.Vbe.Interop.vbext_ComponentType.vbext_ct_StdModule);
xlmodule.CodeModule.AddFromString(sb.ToString());
appl.Run("InsertCascadingDropDown");
Run Code Online (Sandbox Code Playgroud)
当宏执行添加验证的行时,这会导致运行时错误“1004”:
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="=INDIRECT(A5)"
Run Code Online (Sandbox Code Playgroud)
所以这让我相信选择对象没有定义(或者更重要的是它是空的,这取决于你如何解释Selection一词)。
当我发现这一点时,我对此进行了尝试并最终停止了代码控制并手动添加了验证:
源当前评估为错误。
这是一个铁证,选择对象不为空,A5 下拉列表的选择/值实际上是空的!
添加级联下拉列表需要其父级具有值!
所以这就是您需要做的:
pick1.Value2 = "A"; //< set the parent to have a value
pick2.Validation.Delete(); //<- this is not really needed, unless you run this again
pick2.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, "=INDIRECT(A5)");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
987 次 |
| 最近记录: |