Cannot set Data Validation in Excel by using MATCH formula C# - c#

After use MATCH formula to validationStr, my class went wrong.
Can anyone tell me why error happened?
ERROR:
System.Runtime.InteropServices.COMException: 'Exception from HRESULT: 0x800A03EC'
Thank you very much!
using Microsoft.Office.Interop.Excel;
string validationListStr = "=OFFSET($AB$12,1,MATCH($T$12,$AB$12:$AD$12,0)-1,COUNTA(OFFSET($AB$12,1,MATCH($T$12,$AB$12:$AD$12,0)-1,100,1)),1)";
workSheet.Cells[1, 1].Validation.Delete();
workSheet.Cells[1, 1].Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertInformation, Type.Missing, validationListStr, Type.Missing);
workSheet.Cells[1, 1].Validation.IgnoreBlank = true;
workSheet.Cells[1, 1].Validation.InCellDropdown = true;
I set the formula to validation by hand in Excel. There was no problem.
However, I cannot set the formula by C#.

The wrong 'Missing' object is being passed to the Add function.
System.Type.Missing needs to be changed to System.Reflection.Missing.Value
workSheet.Cells[1, 1].Validation.Add(
XlDVType.xlValidateList,
XlDVAlertStyle.xlValidAlertInformation,
Missing.Value, // <-
validationListStr,
Missing.Value // <-
);

Related

Excel Vlookup with C#

I am trying to use WorksheetFunction.VLookup but I get the message:
"VLookup method of WorksheetFunction class failed"
my code:
Excel.Range xlRange = (Excel.Range)xlWorksheet.get_Range("3:1", "333:20");
label4.Text = xlApp.WorksheetFunction.VLookup("MAF0510530146", xlRange, 7, false);
do you have any idea what went wrong?
the input string "MAF0510530146" is in the excel file...
Thanks

Why am I getting a superfluous sheet even though I'm explicitly setting sheet count to 1?

I want to avoid generated spreadsheets having empty/superfluous sheets named "Sheet1" and such. I thought I could do that by specifying how many sheets a workbook should have this way:
_xlApp = new Excel.Application { SheetsInNewWorkbook = 1 };
...But I'm still getting an unwanted "Sheet1" in addition to the sheet I create. Here is the pertinent code:
using Excel = Microsoft.Office.Interop.Excel;
. . .
private Excel.Application _xlApp;
private Excel.Workbook _xlBook;
private Excel.Sheets _xlSheets;
private Excel.Worksheet _xlSheet;
. . .
private void InitializeSheet()
{
_xlApp = new Excel.Application { SheetsInNewWorkbook = 1 };
_xlBook = _xlApp.Workbooks.Add(Type.Missing);
_xlBook.Worksheets.Add(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
_xlSheets = _xlBook.Worksheets;
_xlSheet = (Excel.Worksheet)_xlSheets.Item[1];
_xlSheet.Name = String.Format("Price Compliance {0} {1}", _month, _year);
}
So since setting SheetsInNewWorkbook to 1 in the Excel.Application instance doesn't do the trick, what do I need to do to prevent these tramp sheets from showing up?
The answer to your question can be found in the documentation of the Template parameter on the Workbook.Add method.
[...] If this argument is omitted, Microsoft Excel creates a new
workbook with a number of blank sheets (the number of sheets is set by
the SheetsInNewWorkbook property).
Your code is omitting it, therefore it is creating a single Worksheet for you (since you've set SheetsInNewWorkbook to 1.
That property is also constrained to be between 1 and 255, so you aren't able to add a work book without a sheet (unless you use a file template).
Also from the Template parameter documentation:
If this argument is a constant, the new workbook contains a single
sheet of the specified
type. Can be one of the following Microsoft.Office.Interop.Excel.XlWBATemplate
constants: xlWBATChart, xlWBATExcel4IntlMacroSheet, xlWBATExcel4MacroSheet,
or xlWBATWorksheet.
So an alternative way to do this is:
_xlApp = new Excel.Application();
_xlBook = _xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
_xlSheets = _xlBook.Worksheets;
_xlSheet = (Excel.Worksheet)_xlSheets.Item[1];
_xlSheet.Name = String.Format("Price Compliance {0} {1}", _month, _year);
Which simply renames the single created sheet.

Cut and Paste Columns in Excel Range with c#

I'm trying to move column B in front of column Q in an excel sheet as part of a report I'm working on. I have experience in VBA but relatively little in c# so I've spent the last hour on Google and can't find a solution, I feel like this should be simple but I can't quite get it.
Method one, which results in a “Insert method of Range class failed” msg.
Excel.Range rngCut1 = JobLabourSheet.get_Range("B:B", Type.Missing);
Excel.Range rngPaste1 = JobLabourSheet.get_Range("Q:Q", Type.Missing);
rngCut1.Columns.Cut(rngPaste1.EntireColumn.Insert(Excel.XlInsertShiftDirection.xlShiftToRight, rngCut1));
Method two results in a “Unable to get a Cut property of the Range class” msg.
Excel.Range rngCut1 = JobLabourSheet.get_Range("B:B", Type.Missing);
Excel.Range rngPaste1 = JobLabourSheet.get_Range("Q:Q", Type.Missing);
rngCut1.Columns.Cut(rngPaste1.EntireColumn.Insert(Excel.XlInsertShiftDirection.xlShiftToRight, Missing.Value));
In the second method when I omit the CopyOrigin I get the msg but it does insert a blank column in front of column Q.
In VBA I would use the following:
Columns("B:B").Cut
Columns("Q:Q").Insert Shift:=xlToRight
But like I said, my c# experience is limited at the moment so I have no idea how to go about translating it to c#
This isn't very intuitive, but this is how I got it to work. I took an "insert" range and used the Insert() method and passed a "range.Cut()" method as the "Copy Origin" parameter.
Reference docs:
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.insert.aspx
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.xlinsertshiftdirection.aspx
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.cut.aspx
Here is a sample app (be sure to add a reference to Microsoft.Office.Interop.Excel):
using System;
using System.Collections.Generic;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelCutAndInsertColumn
{
class Program
{
static void Main(string[] args)
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWb = xlApp.Workbooks.Open(#"C:\stackoverflow.xlsx");
Excel.Worksheet xlWs = (Excel.Worksheet)xlWb.Sheets[1]; // Sheet1
xlApp.Visible = true;
// cut column B and insert into A, shifting columns right
Excel.Range copyRange = xlWs.Range["B:B"];
Excel.Range insertRange = xlWs.Range["A:A"];
insertRange.Insert(Excel.XlInsertShiftDirection.xlShiftToRight, copyRange.Cut());
}
}
}

Highlight Cells Rules Text contains

I have the following function =AND(EXACT(B3;F3);EXACT(F3;J3)) which returns TRUE or FALSE.
I'd like to create a cell rule for coloring red the false and green the true values.
Trying to use the following code, but not working, what am i doing wrong?
Excel.FormatConditions fcs = xlWorkSheet.Cells[i,"M"].FormatConditions;
Excel.FormatCondition fc = (Excel.FormatCondition)fcs.Add(Excel.XlFormatConditionType.xlTextString, Excel.XlFormatConditionOperator.xlEqual, "TRUE");
Excel.Interior interior = fc.Interior;
interior.Color = ColorTranslator.ToOle(Color.LightGreen);
Excel.Font font = fc.Font;
font.Color = ColorTranslator.ToOle(Color.ForestGreen);
fc = (Excel.FormatCondition)fcs.Add(Excel.XlFormatConditionType.xlTextString, Excel.XlFormatConditionOperator.xlEqual, "FALSE");
interior.Color = ColorTranslator.ToOle(Color.LightSalmon);
font.Color = ColorTranslator.ToOle(Color.Red);
You are not associating the colors with the given rules (but with variables not related to the Conditional Formatting). Also you should better rely on xlCellValue. This code delivers what you are after:
Excel.FormatCondition fc = (Excel.FormatCondition)fcs.Add(Excel.XlFormatConditionType.xlCellValue, Excel.XlFormatConditionOperator.xlEqual, "TRUE", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
fc.Interior.Color = ColorTranslator.ToOle(Color.LightGreen);
fc.Font.Color = ColorTranslator.ToOle(Color.ForestGreen);
fc = (Excel.FormatCondition)fcs.Add(Excel.XlFormatConditionType.xlCellValue, Excel.XlFormatConditionOperator.xlEqual, "FALSE", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
fc.Interior.Color = ColorTranslator.ToOle(Color.LightSalmon);
fc.Font.Color = ColorTranslator.ToOle(Color.Red);
(Apologize for posting this as an answer, but I don't have enough rep to add a comment yet)
You have line:
Excel.FormatCondition fc = (Excel.FormatCondition)fcs.Add(Excel.XlFormatConditionType.xlTextString, Excel.XlFormatConditionOperator.xlEqual, "TRUE");
And your third parameter "TRUE" would normally represent the formula. If you want this to work, you'll need to change it to "=TRUE". Similarly, you have "FALSE" which should be updated to "=FALSE".
You'll also want to include #varocarbas suggestions above.

Why Application.get_Caller(Type.Missing) returns a negative integer?

There's something weird about get_Caller(Type.Missing) method. It returns a negative integer, -2146826265, instead of the Range object as it should.
Has anyone come across this issue before? Why is that and how should I solve it?
Thanks.
Excel.Range range = (Excel.Range) application.get_Caller(System.Type.Missing);
The above code would fail if I try to explicitly user type Excel.Range. The error message says, 'Cannot convert type 'int' to 'Microsoft.Office.Interop.Excel.Range'.
EDIT:
The intention of getting caller of the cell is to pass it to my following function:
private string getResultFromResultSheet(Excel.Range originalSheetRange, Excel.Worksheet resultSheet)
{
string DataResult = "";
try
{
string os_currentAddress = originalSheetRange.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);
Excel.Range currentRRange = null;
currentRRange = resultSheet.get_Range(os_currentAddress, Type.Missing);
if (currentRRange != null)
{
if (string.IsNullOrEmpty(Convert.ToString(currentRRange.Value)))
DataResult = "";
else
DataResult = Convert.ToString(currentRRange.Value);
}
}
catch (Exception ex)
{
}
return DataResult;
}
With the return value from that function, I can pass it back to UDF and display it in the original cell. Is there any better way to implement the function?
Review the table at the end of this MSDN Library article about the Application.Caller property. You've discovered the value of the #REF! error. Google 'excel error 2023' for additional info. I kinda doubt you can use this property, given that the caller is your C# program.

Categories