Я использую ExcelDNA и Microsoft.Office.Interop.Excel, чтобы установить для некоторых значений y данной серии диаграмм Excel значение #N/A. (*)
Это то, что я пытаюсь достичь в VBA. Это работает так, как ожидалось:
Sub test()
Dim xdata As Variant, ydata As Variant
Dim chrt As Chart
Set chrt = ActiveWorkbook.Worksheets("Sheet1").ChartObjects("Chart 1").Chart
With chrt
xdata = Array(0, 1, 2, 3, 4, 5)
ydata = Array(0, 10, 20, CVErr(xlErrNA), 40, 50) 'Works as expected
.SeriesCollection(1).XValues = xdata
.SeriesCollection(1).Values = ydata
End With
End Sub
В F# я пробовал 2 следующих подхода, и ни один из них не работал:
module TEST =
open Microsoft.Office.Interop.Excel
open ExcelDna.Integration
let series : Series =
let app = ExcelDnaUtil.Application :?> Application
let wks = (app.Sheets.Item "Sheet1") :?> Worksheet
let cho = wks.ChartObjects("Chart 1") :?> ChartObject
let ch = cho.Chart
let s = ch.SeriesCollection(1) :?> Series
s
[<ExcelFunction(Category = "Chart", Description = "")>]
let setYSeries1() : obj =
let s = series
s.XValues <- [| 0.0; 1.0; 2.0; 3.0; 4.0; 5.0 |]
s.Values <- [| 0.0; 10.0; 20.0; 30.0; 40.0; 50.0 |] |> Array.map box // Works as expected.
box "Done."
[<ExcelFunction(Category = "Chart", Description = "")>]
let setYSeries2() : obj =
let s = series
s.XValues <- [| 0.0; 1.0; 2.0; 3.0; 4.0; 5.0 |]
s.Values <- [| box 0.0; box 10.0; box 20.0; ExcelError.ExcelErrorNA |> box; box 40.0; box 50.0 |] |> Array.map box // y = 42 for x = 3, instead of y = #N/A
box "Done."
[<ExcelFunction(Category = "Chart", Description = "")>]
let setYSeries3() : obj =
let s = series
s.XValues <- [| 0.0; 1.0; 2.0; 3.0; 4.0; 5.0 |]
s.Values <- [| box 0.0; box 10.0; box 20.0; ((int32) -2146826246) |> box; box 40.0; box 50.0 |] // y = -2146826246 for x = 3, instead of y = #N/A
box "Done."
setYSeries1
— это базовый случай без значений #N/A. Это работает нормально.
setYSeries2
был естественным способом с использованием перечисления ExcelError.ExcelErrorNA
ExcelDNA, но #N/A заменяется значением перечисления на диаграмме (y = 42).
Я попробовал setYSeries3
после того, как прочитал в этой статье, что внутри Excel использует целые числа для представления ошибок, таких как #N/A (в то время как Excel использует двойные числа для представления чисел), заменяя (int) -2146826246
значение #N/A. Тоже не повезло.
Мой вопрос: что мне делать, чтобы передать значения #N/A массиву .Values серии?
(*) Мне нужно установить свойства серии .Values через массив, а не через диапазон листов.
Вам нужно преобразовать значение ошибки в тип, который .NET будет понимать как тип ошибки COM (например, CVErr
в VBA).
Существует помощник Excel-DNA, который сопоставляет перечисления ошибок C API с ошибками COM:
ExcelDna.Integration.ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)
Внутренне это будет делать
new System.Runtime.InteropServices.ErrorWrapper(-2146826246)
Большое спасибо! Оба метода работают (используя
ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)
или используяSystem.Runtime.InteropServices.ErrorWrapper
).