2010-11-12 94 views
3

我正在使用Excel的COM接口,並且希望獲取單元格的格式化文本表示形式,而不是真正的基礎值。如何讀取Excel中單元格的格式化文本表示形式

例如,假設單元格包含數字1.23456,並且用戶已指定數字格式並帶有一個小數位。然後,我希望能夠讀取字符串"1.2"。我知道我可以使用Range.Text,但是這在一些重要方面失敗了。 Range.Text返回用戶在工作表視圖中看到的內容,因此如果該單元格隱藏,則會返回空字符串。如果單元格的寬度很小,則返回截斷的字符串。 Range.Text也因爲限制爲1024個字符而下降。

另一個用例是當單元格計算出錯誤時,例如, #DIV/0!,#NAME?, #REF!等。我知道我可以讀取Range.Value並測試變體是否爲varError(我正在使用Delphi,在VBA中它將是vbError)。我想不出的是如何獲得文本表示#DIV/0!等等。Range.Text再次返回,但如果該單元格被隱藏或太窄,則不會。

編輯

我認爲,在Range.Text的限制實際上是255個字符。

回答

3

建立在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 
+0

當單元格包含超過255個字符時,此操作失敗 – 2010-11-14 20:26:32

+0

其格式函數具有255個字符限制 - 嘗試修改後的版本只在數值爲數字時才使用格式。 – 2010-11-15 08:39:02

+0

這似乎很有希望,但Format是一個VBA函數。我使用COM(它是一個COM加載項),我不確定是否有可用的等效函數。 – 2010-11-15 12:05:44

2

爲了得到一個隱藏的單元不包含一個錯誤的文本:

Application.WorksheetFunction.Text(the_cell.Value, the_cell.NumberFormat) 

如果它是一個錯誤,這將失敗。所以,你可能想先檢查:

Application.WorksheetFunction.IsError(the_cell) 

不幸的是,這是很難搞清楚你有什麼樣的錯誤爲Error.Type功能不可用VBA中或COM對象。解決此問題的方法是將該公式寫入同一工作表中的另一個單元格中並讀取其值。

+0

再次,當單元格包含超過255個字符時,將失敗。我越試圖研究這一點,我越懷疑這是不可能的。 – 2010-11-14 20:27:07

2

非常感謝Charles的回答和有用的意見。我現在將我需要的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; 
相關問題