両方の組み合わせが必要です。ユーザーは、セルに日付または特定のテキストを入力できる必要があります。
次のコードスニペットは、ワークシートのセルA1に必要な検証を設定します。
Excel.Range range = xlWorkSheet.Range["A1"];
range.ClearFormats();
range.Validation.Delete();
range.Validation.Add(Excel.XlDVType.xlValidateCustom,
Formula1: "=OR(EXACT(LEFT(CELL(\"format\",A1)),\"D\"),EXACT(A1,\"train\"))");
最も複雑な部分は、実際の検証式です。次の機能を使用します。
EXACT(cell,string)
セルの内容をリテラル文字列と比較し、TRUE
それらがまったく同じである場合にのみ返します。
CELL("format",cell)
指定されたセルの形式を含むコードを返します。日付のコードは常に。で始まりますD
。説明と考えられるすべてのコードのリストについては、OfficeヘルプをCELL
参照してください。このスニペットは最初の文字のみを調べます。これはD
、コンテンツをある種の日付としてフォーマットするために必要です。
LEFT(text,count)
の左端のcount
文字をtext
返しますcount
。デフォルトは1です。この場合、TRUE
内容が何らかの日付である場合に返されます。
OR(logical1, logical2)
を返すlogical1 OR logical2
のでTRUE
、内容が日付であるか、文字列と完全に等しい場合"train"
。
A1
数式にハードコードされているため、このソリューションはまだ理想的ではありません。ここINDIRECT
で説明する、を使用してそれを回避する方法があります。たとえば、検証をセルの全範囲に一度に適用する場合は、これが必要になることがあります。その場合、ハードコードされたものを、現在のシェルを示すメカニズムであるに置き換える必要があります。のショートカットとして読むことができます。A1
INDIRECT("RC",FALSE)
INDIRECT("R"&ROW()&"C"&COLUMN(),FALSE)
この調整により、コードの最後の行は次のようになります(Excelでテストされていますが、C#ではテストされていません)。
range.Validation.Add(Excel.XlDVType.xlValidateCustom,
Formula1: "=OR(EXACT(LEFT(CELL(\"format\",INDIRECT(\"RC\",FALSE))),\"D\"),EXACT(INDIRECT(\"RC\",FALSE),\"train\"))"
アップデート
OPが指摘しているように、日付が最初にセルに入力されてから、誤った文字列または数値に変更された場合、このアプローチには問題があるようです。以下のコメントを参照してください。したがって、この関数を使用CELL
することは最善のアプローチではないようです。
ただし、セル形式が(より柔軟な)Text
形式に明示的に設定されている場合は、次の行で検証を課すことができます。
range.Validation.Delete();
range.NumberFormat = "Text";
range.Validation.Add(Excel.XlDVType.xlValidateCustom,
Formula1: =OR(ISNUMBER(DATEVALUE(INDIRECT(\"RC\",FALSE))),EXACT(INDIRECT(\"RC\",FALSE),\"train\"));
再びExcelでテストされましたが、C#からはテストされていません。