Forum Discussion

DKNP's avatar
DKNP
Occasional Contributor
8 years ago

Swing table - Getting the visible value from a cell not the underlying data (Currency Datatype)

Hi

 

I have a table that contains numbers in currency format. When I use Table.FindRow with the row parameter set to the number or string I get "an unexpected error."

 

I note that this only occurs when I do the lookup on columns with currency data, string data works fine. As an aside I haven't tested the other types, I will do so at the earliest opportunity.

 

After a quick search I found what I hoped would solve my problem...see link below, however this also fails for the same reason as the FindRow, namely the field is a currency value.

 

Getting Display format of the data filed in a java swing table

 

Having drilled down a bit further into the way the linked function works, The GetValueAt method works fine with strings (returns the value property), however with decimals it does not return the value property, it only returns the type (in this case BigDecimal). If you use Set when populating the Value variable to set it to an object it also throws an error.

 

It is still possible to get the value using .ToString.OleValue, however, this removes all the formatting which is what I was trying to look for.

 

Does anyone have a reliable way of searching for non-string values in a swing table, which they would be willing to share?

 

Many thanks

 

Peter Mitcham

  • HKosova's avatar
    HKosova
    SmartBear Alumni (Retired)

    Hi Peter,


    DKNP wrote:

     

    Having drilled down a bit further into the way the linked function works, The GetValueAt method works fine with strings (returns the value property), however with decimals it does not return the value property, it only returns the type (in this case BigDecimal).


    It does return the value, not the type. The value is a BigDecimal instance and has all methods and properties of BigDecimal. It just does not have a property that contains the value, you'll need to use instance methods to get that value. E.g. you can use .doubleValue() to get the value as double.

     


    DKNP wrote:

     

    I have a table that contains numbers in currency format. When I use Table.FindRow with the row parameter set to the number or string I get "an unexpected error."


    Using FindRow with BigDecimals is tricky. I guess FindRow uses something like .equals() or .compareTo() internally, so you'll need to create a BigDecimal that represents the sought-for value - so that the sought-for value is of the same type as the column. Here's how you can do this:

    ' Returns a BigDecimal corresponding to the specified string representation.
    ' Parameters:
    '   javaw - The application's java or javaw process, e.g. Sys.Process("javaw")
    '   str - the value as a string, e.g. "15.98"
    ' Return value:
    '   A java.math.BigDecimal object with the specified value
    Function newBigDecimalFromString(javaw, str) Dim jApi : Set jApi = javaw.JavaRuntime().JavaClasses Set newBigDecimalFromString = jApi.java_math.BigDecimal.newInstance_4(str) End Function

    Then you can use:

    Dim javaw : Set javaw = Sys.Process("javaw")
    ...
    Dim value : Set value = newBigDecimalFromString(javaw, "15.98")
    row = table.FindRow("Price", value)

    But it's still tricky. You'll need to know the exact BigDecimal value, whereas the grid could display rounded values. There're also precision issues, so BigDecimal("15.98") != BigDecimal(15.98), because the latter may actually be 15.98000001.

     

     

    A better approach could be to search the column manually for the displayed value, which brings us back to the getRenderedValue() function that you mentioned. I tried it with one sample app and it worked fine, so I'm not sure what might be wrong. From your mention of "Set" I assume you are using VBScript -- can you try this version instead?

    Function getRenderedValue(table, row, column)
      Dim value
    
      If aqObject.GetVarType(table.getValueAt(row, column)) = varDispatch Then
        Set value = table.getValueAt(row, column)
      Else
        value = table.getValueAt(row, column)
      End If
    
      Set renderer = table.getCellRenderer(row, column).getTableCellRendererComponent(table, value, False, False, row, column)
      If aqObject.IsSupported(renderer, "getText") Then
        value = renderer.getText().OleValue
      End If
    
      ' Try to convert the resulting value to a primitive (e.g. java.lang.String -> plain string).
      ' If not possible, return the object value as is.
      On Error Resume Next
      getRenderedValue = value
      If Err.Number <> 0 Then
        Set getRenderedValue = value
        Err.Clear
      End If
    End Function

    If this works, you could perform the search like this:

    row = -1
    strValue = "$15.98"
    For i = 0 To table.wRowCount
      If getRenderedValue(table, i, 2) = strValue Then
        row = i
        Exit For
      End If
    Next

    If row <> -1 Then
    ' Found
    Else
    ' Not found
    End If

     Let us know if this helps.

    • Colin_McCrae's avatar
      Colin_McCrae
      Community Hero

      HKosova

       

      Think there may be another little typo in there?

       

      Your function using the renderer is called "getRenderedValue" but in your second code snippet, you are making a call to "getDisplayValue"?

       

      Thinking they should both be the same name?

       

      Besides that, it looks like exactly the sort of solution I hoped you'd come up with! :)

      • HKosova's avatar
        HKosova
        SmartBear Alumni (Retired)

        Colin_McCrae wrote:

        HKosova

         

        Think there may be another little typo in there?

         

        Your function using the renderer is called "getRenderedValue" but in your second code snippet, you are making a call to "getDisplayValue"?

         

        Thinking they should both be the same name?


        Fixed, thanks.

  • I think you may be on the right track.

     

    The value is just that. A value. Which you mentioned you can get back.

     

    But I suspect you may have to query the renderer (mentioned in the post you linked to) to get the formatting used. It alludes to that on this reference page for building such tables:

     

    https://tips4java.wordpress.com/2008/10/11/table-format-renderers/

     

    Not sure exactly how you'd query this in TestComplete. Thinking this may be another one that HKosova might know about! :)

  • shankar_r's avatar
    shankar_r
    Community Hero

    You can try like this way.

     

    aqConvert.VartoStr(objTable.getValueAt(0,1))

     

    Or

     

    aqConvert.VartoStr(objTable.wItem(0,1))

     

    It always returns the exact value from the Swing Table. In our project we used this method to get different kind of data type values from a Swing Table cell.

    • DKNP's avatar
      DKNP
      Occasional Contributor

      Hi

       

      Thanks for solution of converting the type to string, however, when I tried it against the cell I was having the problem with, it returned blank.

       

      I have tested this further by testing the wValue(x,y) property (which in effect is a wrapper for GetValueAt method) against the following field data types:

       

      String - returns correctly

      Int\Long - returns correctly

      Decimal\Currency - blank

      Date - blank

       

      It would appear that the GetValueAt() only works with primitive data types.

       

      Do Smartbear have a solution for this problem?

      • Colin_McCrae's avatar
        Colin_McCrae
        Community Hero

        Did you look into querying the renderer?

         

        It is, in effect, a different object to the table. But it is used in conjunction with it.

         

        I think you just need a different property to the one mentioned my HKosova in this post here. The renderer determines the formatting in these things so I suspect that's the part you're going to have to look at if you want to get beyond the raw data.