如何在Excel中读取单元格的格式化文本表示
我使用的COM接口到Excel中,我想获得一个单元格格式的文本表示,而不是真正的基础值。
例如,假设单元格包含数字1.23456
,并且用户已经指定了带有一个小数位的数字格式。 然后我想能够读取string"1.2"
。 我知道我可以使用Range.Text
但是这在一些重要的方面失败了。 Range.Text
返回用户在工作表视图中看到的内容,如果单元格被隐藏,则返回空string。 如果单元格的宽度很低,则返回截断的string。 Range.Text
也下降,因为它被限制为1024个字符。
另一个用例是单元格计算出错误,例如#DIV/0!
, #NAME?
, #REF!
等等。我知道我可以读取Range.Value
并testingvariables是否typesvarError
(我使用Delphi,在VBA中它将是vbError
)。 我想不出的是如何获得文本表示#DIV/0!
等Range.Text
返回这个,但不是如果单元格被隐藏或太窄。
编辑
我认为Range.Text的限制实际上是255个字符。
build立在Steven的答案上:尝试这个VBA代码。
由于排队要求,它没有正确处理会计格式,但不清楚在这种情况下你想要做什么。
Sub testing() Dim oRng As Range Dim var As Variant Set oRng = Range("a3") If IsError(oRng) Then var = cstrError(oRng.Value) Else var = oRng.Value2 If IsNumeric(var) Then var = Format(var, oRng.NumberFormatLocal) End If MsgBox Len(var) & " " & var End Sub Function cstrError(vError As Variant) As String Select Case CLng(vError) Case xlErrDiv0 cstrError = "#DIV/0!" Case xlErrNA cstrError = "#N/A" Case xlErrName cstrError = "#NAME?" Case xlErrNull cstrError = "#NULL!" Case xlErrNum cstrError = "#NUM!" Case xlErrValue cstrError = "#VALUE!" Case xlErrRef cstrError = "#REF!" Case Else cstrError = "#N/A" End Select End Function
获取不包含错误的隐藏单元格的文本:
Application.WorksheetFunction.Text(the_cell.Value, the_cell.NumberFormat)
如果是错误,则失败。 所以你可能要先检查一下:
Application.WorksheetFunction.IsError(the_cell)
不幸的是,由于Error.Type
函数不适用于VBA或COM对象,所以很难弄清楚你有什么样的错误。 解决此问题的方法是将该公式写入同一工作表中的另一个单元格中并读取其值。
谢谢你的回答和有用的评论。 我现在拼凑了一个我需要的Delphi / COM版本,如下所示:
function GetCell(const Sheet: ExcelWorksheet; const Row, Col: Integer): string; function ErrorText(const Cell: ExcelRange; hr: HRESULT): string; const ErrorBase=HRESULT($800A0000); var i: Integer; begin Result := Cell.Text; for i := 1 to Length(Result) do begin if Result[i]<>'#' then begin exit; end; end; if hr=ErrorBase or xlErrDiv0 then begin Result := '#DIV/0!'; end else if hr=ErrorBase or xlErrNA then begin Result := '#N/A'; end else if hr=ErrorBase or xlErrName then begin Result := '#NAME?'; end else if hr=ErrorBase or xlErrNull then begin Result := '#NULL!'; end else if hr=ErrorBase or xlErrNum then begin Result := '#NUM!'; end else if hr=ErrorBase or xlErrRef then begin Result := '#REF!'; end else if hr=ErrorBase or xlErrValue then begin Result := '#VALUE!'; end else begin Result := 'an error'; end; end; var Cell: ExcelRange; hr: HRESULT; begin Cell := GetCellAsRange(Sheet, Row, Col); if VarIsError(Cell.Value, hr) then begin raise ECellValueError.CreateFmt( 'Cell %s contains %s.', [R1C1toA1(Row,Col), ErrorText(Cell, hr)] ); end else if VarIsNumeric(Cell.Value) then begin Result := Sheet.Application.WorksheetFunction.Text(Cell.Value, Cell.NumberFormatLocal); end else begin Result := ConvertToString(Cell.Value); end; end;