2017-06-11

25: To Read from and Write to Spread Sheet Cells, Part Three

<The previous article in this series | The table of contents of this series | The next article in this series>

Main Body START

How to Write to an Arbitrary Spread Sheet Cell in the Appropriate Datum Type from Java or Basic Macro Programs Is Explained

About: UNO (Universal Network Objects)

About: LibreOffice

About: Apache OpenOffice

About: Java Programming Language

A Note

This series is about developing UNO extensions that consist of Java UNO components, but most of its descriptions also apply to using UNO in external Java programs or Basic macros (handling spread sheets is inevitably using UNO because spread sheets are UNO objects). The only difference for using UNO in external Java programs is how to get the component context, and the difference is dealt with in the series, 'How to Use UNO (Handle LibreOffice or Apache OpenOffice Documents) in External Java Programs'. As for using UNO in Basic macros, in addition to how to get the component context, there are some other differences, and those differences are dealt with in the series, 'Notes About Using UNO (Handling LibreOffice or Apache OpenOffice Documents) in Basic Macros'.

How Can We Set an Arbitrary Value to an Arbitrary Spread Sheet Cell in the Appropriate Datum Type?

-Hypothesizer

Now that we have a reference to the representative cell of an arbitrary spread sheet cell and know how to read from the spread sheet cell in the appropriate datum type, let's set an arbitrary value to the spread sheet cell.

-Rebutter

OK.

-Hypothesizer

As you can guess from the way in which the value is internally stored in the cell, we can set the value as the double value when the value isn't a string or a formula. However, to do so, we have to transform the value to the appropriate double value.

-Rebutter

For example, we have to transform the date value, 2017-01-01, to the double value, 42736.0.

-Hypothesizer

Apparently, 42736 is the day index of 2017-01-01 as 1 is of 1900-01-01, and we can perform the transformation based on that assumption. However, as we don't want to implement our codes based on such internal specifications, we will turn to another way to set an arbitrary date value to the cell.

-Rebutter

Well, won't that another way cause some significant performance degradation?

-Hypothesizer

Actually, I tested it: in order to set the date value 10,000 times, setting the double value took 15.0 seconds and setting in our way took 15.6 seconds.

-Rebutter

Ah, the difference will be insignificant enough for us.

-Hypothesizer

We can set an arbitrary date value using the 'setFormula' method of the 'com.sun.star.table.XCell' UNO interface implemented by the UNO component of the representative cell UNO object.

-Rebutter

Do we use the 'setFormula' method while we don't set a formula?

-Hypothesizer

That may seem odd, but we do so. After we set the cell value expression format (so-called number format), we call the 'setFormula' method with the cell value expression string as the argument.

-Rebutter

Hmm.

-Hypothesizer

For time, datetime, and boolean values, we set the value in the same way.

-Rebutter

How about integer and double values?

-Hypothesizer

We can set them in the same way, but we will directly set the double value for them, for in that way, we don't need to create the cell value expression string.

-Rebutter

Well, I understand that that's a less cumbersome way for integer and double values.

-Hypothesizer

As we argued in the preceding article, precision of data is crucial for us. So, we have to set the appropriate cell value expression format for an arbitrary double value.

-Rebutter

Ah, so we judge the number of decimal places of the double value, and set the cell value expression format of that number of decimal places. . . . How do we judge the number of decimal places?

-Hypothesizer

When we are dealing with an arbitrary BigDecimal value, we can know it from the value itself. If we are dealing with an arbitrary Double value, it will be have to be specified otherwise if the precision is important.

-Rebutter

I see.

-Hypothesizer

For string values, we set the value by calling the 'insertString' method of the 'com.sun.star.text.XText' UNO interface implemented by the UNO component of the representative cell UNO object. In order to call the method, we have to first get a 'com.sun.star.text.XTextCursor' instance from the representative cell UNO object using the 'com.sun.star.text.XText' UNO interface.

-Rebutter

Don't we have to remove the existing value first before we insert the new string value?

-Hypothesizer

The existing double value seems to be going to be automatically discarded. As for the existing string value, we will clear the string by the 'setFormula' method with the argument, "".

-Rebutter

Can't we set the string value directly by the 'setFormula' method?

-Hypothesizer

If the string value to be set can be interpreted as a formula, for example "= A8 + 1", it will be set as a formula, not as a string value. So, we don't set string values by the 'setFormula' method.

-Rebutter

Ah-ha.

Will the string value be also automatically discarded when an arbitrary double based value is set?

-Hypothesizer

It seems so.

-Rebutter

I see.

-Hypothesizer

We can set an arbitrary formula using the 'setFormula' method.

-Rebutter

Ah-ha.

-Hypothesizer

After all, I have written this at the end of the try block of the previous article.

@Java Source Code
   // Sets the inputted value to the current spread sheet cell START
   String l_specifiedValue = JOptionPane.showInputDialog (null, "Specify a value in the format, '<datum type>: <value>'");
   String l_datumType = null;
   String l_valueExpression = null;
   if (l_specifiedValue != null) {
    int l_colonDelimiterPositionIndex = l_specifiedValue.indexOf (": ");
    if (l_colonDelimiterPositionIndex >= 0) {
     l_datumType = l_specifiedValue.substring (0, l_colonDelimiterPositionIndex);
     l_valueExpression = l_specifiedValue.substring (l_colonDelimiterPositionIndex + 2);
    }
    if (l_datumType != null) {
     switch (l_datumType) {
      case "Formula":
       l_currentSpreadSheetCellInXCell.setFormula (l_valueExpression);
       break;
      case "LocalDate":
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_dateExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setFormula (l_valueExpression);
       break;
      case "LocalTime":
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_timeExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setFormula (l_valueExpression);
       break;
      case "LocalDateTime":
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_dateTimeExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setFormula (l_valueExpression);
       break;
      case "Boolean":
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_booleanExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setFormula (l_valueExpression);
       break;
      case "String":
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_stringExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setFormula ("");
       XTextCursor l_textCursorInXTextCursor = l_currentSpreadSheetCellInXText.createTextCursor();
       l_currentSpreadSheetCellInXText.insertString (l_textCursorInXTextCursor, l_valueExpression, true);
       break;
      case "Integer":
       Integer l_integer = new Integer (l_valueExpression);
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_integerExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setValue (l_integer.intValue ());
       break;
      case "BigDecimal":
       BigDecimal l_bigDeciaml = new BigDecimal (l_valueExpression);
       int l_scale = l_bigDeciaml.scale ();
       if (l_scale > 0) {
        // Register and set the cell value expression format of a specific precision START
        String l_doubleOfSpecificPrecisionExpressionFormatString = String.format (String.format ("%%.%df", l_scale), 0.0);
        int l_doubleOfSpecificPrecisionExpressionFormatKey = l_cellValueExpressionFormatsInXNumberFormats.queryKey (l_doubleOfSpecificPrecisionExpressionFormatString, l_defaultLocale, false);
        if (l_doubleOfSpecificPrecisionExpressionFormatKey == -1) {
         l_doubleOfSpecificPrecisionExpressionFormatKey = l_cellValueExpressionFormatsInXNumberFormats.addNew (l_doubleOfSpecificPrecisionExpressionFormatString, l_defaultLocale);
        }
        // Register and set the cell value expression format of a specific precision END
        l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_doubleOfSpecificPrecisionExpressionFormatKey));
        l_currentSpreadSheetCellInXCell.setValue (l_bigDeciaml.doubleValue ());
       }
       else {
        l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_integerExpressionFormatKey));
        l_currentSpreadSheetCellInXCell.setValue (l_bigDeciaml.intValue ());
       }
       break;
      case "Double":
       Double l_double = new Double (l_valueExpression);
       l_currentSpreadSheetCellInXPropertySet.setPropertyValue ("NumberFormat", new Integer (l_doubleDefaultExpressionFormatKey));
       l_currentSpreadSheetCellInXCell.setValue (l_double.doubleValue ());
       break;
      default:
       Publisher.show ("That datum type isn't recognized.");
       break;
     }
    }
    else {
     Publisher.show ("Wrong format.");
    }
   }
   // Sets the inputted value to the current spread sheet cell END

Besides, I have added these import directives.

@Java Source Code
import javax.swing.JOptionPane;
import com.sun.star.text.XTextCursor;
import com.sun.star.beans.PropertyVetoException;

And I have added this exception type in the catch block.

  • PropertyVetoException
-Rebutter

Hmm, we are setting the value specified in an input dialog to the current spread sheet cell.

-Hypothesizer

The expected format of the input is '<datum type>: <value>', for example 'LocalDateTime: 2017-01-01T00:00:00' and 'BigDecimal: 12.3400'. Note that the space after the colon is necessary.

-Rebutter

I see.

-Hypothesizer

In fact, we have implemented the above code into the test project included in the zip file cited in a previous article. How to use the zip file is described in the article. However, just don't select the 'H1' cell before the 'Test1' button is pushed, because that cell is used in the code of the next article.

Main Body END

<The previous article in this series | The table of contents of this series | The next article in this series>