rookie_developer
rookie_developer

Reputation: 1369

need custom validation (date + particular text) in excel sheet generated using C#

I am looking to have a validation in an excel sheet which is generated using C# such that it allows either date value or the text "train" in the excel cell. I found XlDVType.xlValidateDate for validating date in a cell and XlDVType.xlValidateList to allow text values. But I want a combination of both, user should either be able to enter date or a particular text in the cell. Can this be accomplished using XlDVType.xlValidateCustom ??

any help on this would be greatly appreciated.

Upvotes: 0

Views: 2830

Answers (1)

Reinier Torenbeek
Reinier Torenbeek

Reputation: 17383

I want a combination of both, user should either be able to enter date or a particular text in the cell.

The following code snippet sets the desired validation for cell A1 in your worksheet:

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\"))");

The most complicated part is the actual validation formula. It uses the following functions:

EXACT(cell,string) compares the contents of a cell with a literal string and returns TRUE only if they are exactly the same.

CELL("format",cell) returns a code containing the format of the indicated cell, where the code for a date always starts with a D. See Office help for CELL for an explanation and a list of all possible codes. This snippet only looks at the first character, which has to be a D in order for the contents to be formatted as some kind of date.

LEFT(text,count) returns the leftmost count characters in text, with count defaulting to 1. In this case, it returns TRUE if the contents are some kind of date.

OR(logical1, logical2) returns logical1 OR logical2, so TRUE if the contents are either a date, or exactly equal to the string "train".

This solution is not yet ideal, because A1 is hardcoded into the formula. There is a way around that using INDIRECT, described here. You might need that, for example if you want to apply the validation to a whole range of cells in one go. In that case, the hardcoded A1 needs to be replaced by INDIRECT("RC",FALSE), which is the mechanism to indicate the current shell. You can read it as a short-cut for INDIRECT("R"&ROW()&"C"&COLUMN(),FALSE).

With that adjustment, he last line of code then looks like this (tested in Excel, but not from C#):

range.Validation.Add(Excel.XlDVType.xlValidateCustom,
    Formula1: "=OR(EXACT(LEFT(CELL(\"format\",INDIRECT(\"RC\",FALSE))),\"D\"),EXACT(INDIRECT(\"RC\",FALSE),\"train\"))"

Update

As the OP points out, there appears to be a problem with this approach if a date has first been entered into the cell, and then is changed to an incorrect string or number value -- see the comments below. Using the CELL function therefore does not seem to be the best approach.

However, if the cell format is explicitly set to the (more flexible) Text format, it is possible to impose the validation with the following lines:

range.Validation.Delete();
range.NumberFormat = "Text";
range.Validation.Add(Excel.XlDVType.xlValidateCustom,
    Formula1: =OR(ISNUMBER(DATEVALUE(INDIRECT(\"RC\",FALSE))),EXACT(INDIRECT(\"RC\",FALSE),\"train\"));

Again tested in Excel, but not from C#.

Upvotes: 2

Related Questions