Range Validator in Excel with custom message text - c#

I have the following code to give a Excel cell Validation with custom text.
var cellValues = activeSheet.Range[columnLetterValue + startingRow, Type.Missing];
cellValues.Validation.Add(XlDVType.xlValidateCustom, XlDVAlertStyle.xlValidAlertInformation, XlFormatConditionOperator.xlBetween, cellValues.Value2, Type.Missing);
cellValues.Validation.IgnoreBlank = true;
cellValues.Validation.ErrorTitle = "Custom error title";
cellValues.Validation.ErrorMessage = "Custom error message description";
cellValues.Validation.ShowError = true;
cellValues.Validation.ShowInput = false;
When debugging the line to set the ErrorTitle or ErrorMessage a 'System.Runtime.InteropServices.COMException' is thrown.
Stacktrace:
{System.Runtime.InteropServices.COMException (0x800A03EC): Exception
from HRESULT: 0x800A03EC at
System.RuntimeType.ForwardCallToInvokeMember(String memberName,
BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData&
msgData) at
Microsoft.Office.Interop.Excel.Validation.set_ErrorTitle(String )
I have looked online and found a couple of examples that show this is possible:
Range Validation with Excel using C#
I've even recorded a Macro in Excel and it works with the "VBA" equivilent code:
ActiveCell.FormulaR1C1 = "Custom"
Range("A1").Select
With Selection.Validation
.Delete
.Add Type:=xlValidateCustom, AlertStyle:=xlValidAlertInformation, _
Operator:=xlBetween, Formula1:="Custom"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "UDF Title"
.InputMessage = ""
.ErrorMessage = "The message"
.ShowInput = False
.ShowError = True
End With
End Sub
I've also tried different combinations of XlDVType and XlFormatConditionOperator but that didn't seem to make any difference in setting the custom messagebox text.
Does anyone know how to set a Validation rule with custom ErrorTitle and ErrorMessage?

The problem was due to setting a Validation.ErrorTitle to a range that didn't have a Validation rule.

Related

c# cannot read special character from a text file

In the text file, I create a list for user input their condition, in order to filter out these four value in the excel file.
abc=<>10,<>20,<>30,<>40
And into program, I wrote this to read the list:
try
{
abc = dic["abc"];
if (abc == null || abc.Trim() == "")
{
MessageBox.Show("abc can't be empty!");
this.Close();
}
}
catch (KeyNotFoundException)
{
MessageBox.Show("abc can't be found in Config.txt!");
this.Close();
}
And in the final steps, I want to add the list into string list in my source code, then use autofilter function to filter the excel
string[] abc_list = abc.Split(',');
newSheet.Range["$A:$OO"].AutoFilter(12, abc_list, Excel.XlAutoFilterOperator.xlFilterValues);
And this is the error I got:
23:49:16
Line No.: 5778
System.Runtime.InteropServices.COMException (0x800A03EC): _AutoFilter method of Range class failed
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at Microsoft.Office.Interop.Excel.Range.AutoFilter(Object Field, Object Criteria1, XlAutoFilterOperator Operator, Object Criteria2, Object VisibleDropDown)
But I found that it is not working. Can anyone tell me why?
Thanks.
I found that change .xlFilterValue to .xlOr can solve this question.

Translate Copy / Paste in excel from VBA code to C#

I have this vba code that i am trying to convert into C# using Microsoft.Office.Interop.Excel.
So the code is :
Columns("AN:AS").Select
Selection.Copy
Columns("AT:AT").Select
Selection.Insert Shift:=xlToRight
Columns("AT:AY").Select
Selection.Replace What:="ST", Replacement:="TO", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Application.CutCopyMode = False
I have look into some solutions but i am keep getting errors.
This is what i have done :
Range source = (Microsoft.Office.Interop.Excel.Range)currentSheet.get_Range("AN:AS").Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight);
Range destination = currentSheet.get_Range("AT: AT");
source.Copy(destination);
currentSheet.get_Range("AT:AY").Replace("ST", "TO", SearchOrder : 1 , LookAt : 2, MatchCase: false, SearchFormat: false, ReplaceFormat: false);
currentSheet.Application.CutCopyMode = 0;
And i got error at the source variable saying :
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: Impossible de convertir le type 'bool' en 'Microsoft.Office.Interop.Excel.Range'
My goal is to transform that code from VBA to C#.
My goal is to transform that code from VBA to C#.
that should does the job:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Range source = currentSheet.get_Range("AN:AS");
Excel.Range destination = currentSheet.get_Range("AT:AT");
destination.Insert(XlInsertShiftDirection.xlShiftToRight, source.Copy());
currentSheet.get_Range("AT:AY").Replace("ST", "TO", SearchOrder: 1, LookAt: 2, MatchCase: false, SearchFormat: false, ReplaceFormat: false);
// avoid to have a message about clipboard before saving the file
currentSheet.Application.CutCopyMode = XlCutCopyMode.xlCopy;
Thank you for all the response.
This is what work finally for me.
Range source = currentSheet.get_Range("AN:AS");
source.Select();
source.Copy();
Range destination = (Microsoft.Office.Interop.Excel.Range)currentSheet.get_Range("AT:AT");
destination.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight);
Range range_sheet = currentSheet.get_Range("AT:AY");
range_sheet.Select();
range_sheet.Replace("ST", "TO", SearchOrder: XlSearchOrder.xlByRows, LookAt: XlLookAt.xlPart, MatchCase: false, SearchFormat: false, ReplaceFormat: false);
currentSheet.Application.CutCopyMode = 0;

pagesetup excel Worksheets and i didn't have access control to printer

I faced the problem with a blow code that i need to change the excel page setup(orientation zoom or any property but the default printer is not available, i didn't have permessions to access printer or found so this code raised exception.
xlApp = new Excel.Application();
book = xlApp.Workbooks.Open(fileFullPath);
xlApp.Visible = false;
xlApp.DisplayAlerts = false;
var with1 = book.Worksheets[sheetName].PageSetup;
with1.zoom = false;
with1.FitToPagesWide = 1;
with1.FitToPagesTall = 1;
with1.Orientation = XlPageOrientation.xlLandscape;
the exception is:
Exception: System.Runtime.InteropServices.COMException
Message: Unable to set the Zoom property of the PageSetup class
Target Site: Void CheckThrowException(Int32, System.Dynamic.ExcepInfo ByRef, UInt32, System.String)
Source: Microsoft Excel
Stack Trace: at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message)
at CallSite.Target(Closure , CallSite , ComObject , Boolean )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at CallSite.Target(Closure , CallSite , Object , Boolean )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at ExcelProcessing.ThumbGeneration.ExcelSheetSnapShoot(String fileFullPath, String thumbDir, String sheetName, String thumbResolution, String cropArea, String PDFFilesDir)
note:
the exception happened when no printers found as default to when change page layout properties throw this exception so i need to any other thing to export excel file as lanscape PDF
This is not an answer, but it wouldn't fit in a comment, so I put it here.
I would like to check if the same steps work from another Excel session instead of C#.
Try to start Excel create this macro and run it. It will create a second Excel session just like your C# function does. I tried in my computer and it works.
If it works, then very likely it's a problem with .net.
If it doesn't, then very likely it's a problem with the file the hidden session is opening.
Sub Test()
Dim Exl As New Application, Wb As Workbook, PS As PageSetup
Set Wb = Exl.Workbooks.Open("Test.xls")
Set PS = Wb.ActiveSheet.PageSetup
PS.Zoom = False
PS.FitToPagesWide = 1
PS.FitToPagesTall = 1
PS.Orientation = XlPageOrientation.xlLandscape
Exl.Quit
End Sub

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.

MathType in C# (OLE)

I'm trying to run a MathType in a C# app... using OLE in forms to signify the equations/images.
This is how I started with the code.
I got the CLSID object for math type equation. I create a new instance and run a verb to start Math Type. This works good until I try to set or get data of the IDataItem attribute I have.
Code:
string progID = "Equation.DSMT4";
comRetVal= CLSIDFromProgID(progID, out eqContainerGUID);
Type t = Type.GetTypeFromProgID(progID); //ok-> MT6 Equation
Object instance = Activator.CreateInstance(t);
IDataObject oleDataObject = instance as IDataObject;
MTSDKDN.MathTypeSDK.IOleObject oleObject = instance as IDataObject;
//run verb Run For Conversion - I'm not sure what this verb does
oleObject.DoVerb(2, (IntPtr)0, activeSite, 0, (IntPtr)this.Handle, new MathTypeSDK.COMRECT());
//up to here everything is find
//Now say I want to put a MathML string into the IDataObject
//set format
formatEtc.cfFormat = (Int16)dataFormatMathMLPres.Id; //<-this overflows. I verified that the only format that works is Presentation MAthML
formatEtc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.ptd = (IntPtr)0;
formatEtc.tymed = TYMED.TYMED_HGLOBAL;
//set medium
ConnectSTGMEDIUM stgMedium = new ConnectSTGMEDIUM();
string mathEqn = "<math><mi>x</mi></math>";
stgMedium.unionmember = Marshal.StringToHGlobalAuto(mathEqn);
stgMedium.pUnkForRelease = 0;
//if now i write the equation to console from STGMEDIUM i see that after each char there is a null. Is this normal?
//now I try to set data in IDataObject and the OLE object
//I thought this set the data of the ole object to the MathML string I put in STGMEDIUM
oleDataObject.SetData(ref formatEtc, ref stgMedium, false);
The app now crashes with this exception:
System.Runtime.InteropServices.COMException was unhandled Message="Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))" Source="System" ErrorCode=-2147221404 StackTrace: at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)
I'm not sure what this means, but I think it might have to do with
formatEtc.cfFormat = (Int16)dataFormatMathMLPres.Id;
because that ID is 50000 and does not fit in a short (cfFormat is a short) so it overflows to something like -15000.
I have solved similar issue by converting it from unsigned to signed value. it means that if the value (dataFormatMathMLPres.Id) is grater than 32767. Use (dataFormatMathMLPres.Id - 65536) instead. It will fit signed short.

Categories