How to automaticaly convert a Text Cell (US Eng) to Date / Time (Eu) with a macro?

Dear Community,
I am trying to import a csv File (exported from Thunderbird) and adjust it in a way that the unnecessary parts are deleted, and some time calculations are done. For this task I wrote the following macro.
It works fine except of the part, where I use "dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())" to convert the Text Cell to a date or time cell. With this function I have to select the desired properties manually.
I am searching for a possibility to either set the right properties while linking the CSV file, or to perform
" dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())" with automatically selecting and applying the desired properties.
After the conversion from text to “Date” or “US English” the change to display it in a desired format is working as intended as long as at least 1 date and 1 time cell was predefined correctly. Otherwise it will display the wrong format. "dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())" with args1().value = 121 seems only to work properly if libre office already knows which User-defined format is desired.
Is there a way to tell libre office which exact user defined format is desired for displaying the date and time?
After the macro finished its performance the resulting ods should show the Date in European style: DD/MM/YYYY and the time from 00:00 to 24:00.
I added an example csv File (remove .xls and replace it with .csv) and the corresponding result (ods) . I hope someone can help me out with this.
Best regards,
Thomas
Time test.ods (14.1 KB)
Time test.xls (854 Bytes)

Edit: Code formatting

Sub Worktimeconverter
Dim sPath As String, sTitle As String, sFilename As String, sSheetname As String      REM_________________________________________________________________________________ REM Select CSV File 
Dim oFilePicker	: oFilePicker = CreateUnoService( "com.sun.star.ui.dialogs.FilePicker" )
        	oFilePicker.setTitle( sTitle )
        	oFilePicker.setDisplayDirectory( sPath )
        	If oFilePicker.execute() = 1 Then selectFile = oFilePicker.getDirectory()
REM_________________________________________________________________________________ REM Import selected File to acutal Sheet and delete unwanted columns
        	Dim  oSheet As Object, oColumns As Variant
        	GlobalScope.BasicLibraries.LoadLibrary("Tools")
         	oSheet=thiscomponent.getcurrentcontroller.activesheet
        	oSheet.link(ConvertToURL(selectFile), _
                            sSheetname, FILTER_NAME, FILTER_OPTIONS, _
                            com.sun.star.sheet.SheetLinkMode.VALUE)
            oSheet.setLinkMode(com.sun.star.sheet.SheetLinkMode.NONE)
            oColumns = oSheet.getColumns()
            oColumns.removeByIndex(5, 4)
            oColumns.removeByIndex(6, 1)
            oColumns.removeByIndex(7, 1)
REM_________________________________________________________________________________
REM Count the Amount of Rows in the CSV File
        	DIM iRow As Integer
        	iRow = 0
        	If oSheet.GetCellByPosition(1,0).String <> "" Then
        		Do
        			iRow = iRow + 1
        		Loop Until oSheet.GetCellByPosition(1,iRow).String = ""
        	End IF
REM_________________________________________________________________________________
REM	Change the Names of the Headers
        	DIM Counter As Integer, Coutner2 As Integer  
        	Counter = 0
        	oSheet.GetCellByPosition(0,Counter).String = "Beschreibung"
        	oSheet.GetCellByPosition(1,Counter).String = "Startdatum"
        	oSheet.GetCellByPosition(2,Counter).String = "Startzeit"
        	oSheet.GetCellByPosition(3,Counter).String = "Enddatum"
        	oSheet.GetCellByPosition(4,Counter).String = "Endzeit"
        	oSheet.GetCellByPosition(5,Counter).String = "Kostenträger"
        	oSheet.GetCellByPosition(6,Counter).String = "Kostenstelle"
        	oSheet.GetCellByPosition(7,Counter).String = "Über Nacht"
        	oSheet.GetCellByPosition(8,Counter).String = "Dauer"
REM	Calculate the Differenz between the Dates and Timestamps
        	if iRow > Counter Then
        		Do
        			Counter = Counter + 1
        			Counter2 = Counter + 1
        			oSheet.GetCellByPosition(7,Counter).Formula = "=D"+Counter2+"-B"+Counter2 
        			oSheet.GetCellByPosition(8,Counter).Formula = "=E"+Counter2+"-C"+Counter2 + "+H"+Counter2 
        		Loop Until Counter = iRow -1 
        	End IF
REM_________________________________________________________________________________
REM Change the Format of the Cells so it shows German time
        dim document   as object
        dim dispatcher as object
        document   = ThisComponent.CurrentController.Frame
        dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
        REM Select Cells -> Dauer und Tageswechsel
        dim args1(0) as new com.sun.star.beans.PropertyValue
        dim args2(0) as new com.sun.star.beans.PropertyValue
        args2(0).Name = "ToPoint"
        args2(0).Value = "H2:I1048576"
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        REM Format Cells -> Dauer und Tageswechsel
        args1(0).Name = "NumberFormatValue"
        args1(0).Value = 121
        dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())
        REM To Convert the other Cells to the right Format use TextToColumns
        args2(0).Name = "ToPoint"
        args2(0).Value = "$B$2:$B$1048576"
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        args1(0).Value = 122
        dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())
        args2(0).Value = "$C$2:$C$1048576"
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())
        args1(0).Value = 121
        dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())
        args2(0).Value = "$D$2:$D$1048576"
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())
        args1(0).Value = 122
        dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())
        args2(0).Value = "$E$2:$E$1048576"
        dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
        dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())
        args1(0).Value = 121
        dispatcher.executeDispatch(document, ".uno:NumberFormatValue", "", 0, args1())
        End Sub

For curiosity:
Why do you need to evaluate such a mess?
If somebody needs to forward dates and/or date-time values or TOD to you, simply tell him to use ISO 8601 (YYYY-MM-DD and HH:MM:SS). There are a few alternatives probably acceptable, but why?
Never ever accept dates in “US format”, and under no circumstances with two-digit-year. Of course also the AM/PM is just a bad joke regarding the purposes of data transmission.
All the contributors having posted to this thread, including myself, already wasted many many hours trying to help people to solve problems with dates and TOD which simply wouldn’t occur if the other partty didn’t refuse to think a bit.
Yes, even LibO uses YY in all locales’ default date formats. It should be beyond belief. Never accept these formats in your documents.

This is a typical Excel dialect of csv with every value quoted and weird date formats. The Excel users exporting this mess don’t know better, although Excel could do better.

Well, the OQ talked of “csv exported from Thunderbird”…
Anyway, it’s surely possible to convert dates to sensibly (ISO) formatted strings, even in Excel.
Data must be identifiable data when communicated to somebody else. Otherwise catastrophes may be caused. Once in a century is too often for some of them.

Are you sure that Excel ignores user chosen number formatting when exporting to csv? LibreOffice didn’t so if correctly used for a long time now (if I remember correctly). Explicit conversion to sensible text is the better way, however.
grafik

Which I read as “detached from email” since I can not find anything in my Thunderbird able to export a csv like this one.

I also tended to this interpretation. However, …

A general hint: Dates and date-time designators complying with ISO 8601 given as texts are auitomatically recognized by Calc when reading them from a csv if Detect Special Numbers is enableds. A specific setting concerning the column type (and YMD order) may then be omitted.

Contents are treated cell by cell now.

  • The respective cells are set to an appropriate number format automatically in this case.
    Unfortunately the well-known nonsense formats (including two-digit-year) are also kept this way.
  • Concerning the date//time separator “T” specified by ISO, there is the relief that a space is accepted in this place (which human readers may prefer.without causing much of an ambiguity).

I think the message is about exporting a calendar.

1 Like

Thank you. Indeed, I get the same csv flavour when I export the TB Calendar to csv. Calc can handle this flawlessly if you understand the meaning of locale (language) and “special numbers”.

Sorry, I did not get the csv renamed to xls.
With these import settings you get 100% correct import data. The dialog settings are saved. Next time all you have to do is clicking [OK].


Raw data:

"Test Text","11/17/21","09:15:00 AM","11/17/21","11:00:00 AM","False","False","","","Test Text","","Test Text","False"

Import locale “English (USA)” because of the M/D/Y dates and AM/PM times
Every single value is quoted by the specified string delimiter, so we need to uncheck “Format quoted field as text”.
“Detect special numbers” is an option that should be turned ON in 99% of all practical cases.
The “FilterOptions” for an import macro using these settings is

44,34,ANSI,1,,1033,false,true,true,false,false
1 Like

Forget about using hard coded number format index numbers. Specifically for user-defined formats they depend on whether a format is defined at all and in which order, thus work only by chance.
Instead, use a proper method to obtain the index / create and apply a format, for example see Format Range to Number and 2 decimal places - #2 by librebel

1 Like

Hi erAck,
I appreciate your advice. I could solve one of 2 issues with it.
The formatting is now working properly.
The only thing left, is the conversion from text to date / time. Right now I use
dispatcher.executeDispatch(document, ".uno:TextToColumns", "", 0, Array())
With this line, libre office calc will bring a pop up and I have to select things manually.
Do you know a solution, which would apply the desired formatting automatically?

You can try this. Operators for assigning the NumberFormat property are omitted.

Sub Worktimeconverter2
  Dim oFilePicker, sPath As String, sTitle As String, selectFile As String, sSheetname As String
  Dim  oSheet, oCursor
  Dim sFilterOption As String, arr, iRow As Long
  oFilePicker = CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
  
  With oFilePicker
    .appendFilter "Csv-files", "*.csv"
    .setTitle(sTitle)
    .setDisplayDirectory(sPath)
    If .Execute=0 Then Exit Sub
    selectFile=.selectedFiles(0)
  End With  
     
  ' Import. See: https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options   
  sFilterOption="44,34,0,1,1/2/2/10/3/10/4/10/5/10/6/9/7/9/8/9/9/9/10/2/11/9/12/2/13/9"
  oSheet=ThisComponent.CurrentController.ActiveSheet
  With oSheet
    .link(selectFile, "", "Text - txt - csv (StarCalc)" , sFilterOption, _
              com.sun.star.sheet.SheetLinkMode.VALUE)
    .setLinkMode(com.sun.star.sheet.SheetLinkMode.NONE)
  
    ' Column headers.
    arr=Array("Beschreibung", "Startdatum", "Startzeit", "Enddatum", "Endzeit", _
              "Kostenträger", "Kostenstelle", "Über Nacht", "Dauer")    
    .getCellRangeByPosition(0,0,Ubound(Arr),0).SetDataArray(Array(arr))  

    ' Formulas
    oCursor = oSheet.createCursor
    oCursor.gotoEndOfUsedArea True
    iRow=oCursor.RangeAddress.EndRow
    .getCellByPosition(7,1).SetFormula("=D2-B2")
    .getCellByPosition(8,1).SetFormula("=E2-C2+H2")
    .getCellRangeByPosition(7,1,8,iRow).fillAuto(0,1)
    
    ' Number formats
    ' ...
    
  End With  
End Sub
1 Like

Thank you for your reply,
I will try this tomorrow and let you know if it could fix my problem.

With your example code and the FileOptionCode from Villeroy,
I could fix my problem.
Thanks a lot.

(Originally posted as a comment. Reposted as an answer now.)
Sigh! That a wide-spread (open) software actually exports “data” to such a monster of .csv file using the worst thinkable “data-formats” internally should be incredible, and -never having exported a calendar this way- I didn’t know. Now I need to rethink the usage of Thunderbird fundamentally. This is inexcusable.

However, a main standard format for the exchange of calendars is iCalendar (standard extension .ics), and it’s the default format Thunderbird uses. It doesn’t resemble csv in any way, but is completely line-oriented and uses a kind of tags in a roughly similar way as xml-based formats do.

If you want to get a calendar for your own use and special evaluation into a spreadsheet, accept the need of the following steps:

  • Export the calendar to a .ics file.
  • Convert the file to csv using a ready-made tool. I would prefer an offline tool (or even write one), but I won’t stop the online plague anyway. Thus I tested Convert ICS to CSV. The result was OK.
  • Rework what you get by rearranging the columns …
  • Insert your duration column (e.g.) with the needed formulas …
  • Add a sheet for special evaluation (e.g.) …
  • Do special steps depending on your needs.