Android Question Download and read .csv

jvrh_1

Active Member
Licensed User
Hello!
I have a problem with my App. It is very simple:

1- Download a Google Sheet (public).
2- Read data.

I think that my App works fine at first, but I have checked that it only read 18 rows of it. I have tried a lot of runtines, but I can not resolve the problem. In addition, I save the .csv in "File.DirInternal" so, I can not review the file because it is not available to any user. Although the first 18 rows are ok, after appears a lot of diferents symbols. I do not know if the problem is in the download process or in the read data process. When I change the File.DirInternal to File.Direxternal appears an erros (I think that may be to any permissions). Any Idea?. Thank you. I am stuck.

The Google Sheet page is public and mine:
My code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    DownloadFile
    leer
    
End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub DownloadFile()
    'download csv file
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
End Sub


Sub leer
    Log("=======LEER =====")
    Dim Reader As TextReader
    Dim S As String
    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
    S = Reader.ReadAll
    Reader.Close
    Log("===========")
    Log(S)
End Sub
 

mcqueccu

Well-Known Member
Licensed User
Longtime User
Upvote 0

jvrh_1

Active Member
Licensed User
DownloadFile is a resumable Sub. You need to Wait For it to complete before running "leer"

or move leer to the end of Downloadfile.
I have move leer to end of Downloadfile and I get the same result:


B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    DownloadFile
    
End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub DownloadFile()
    'download csv file
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    leer
End Sub


Sub leer
    Log("=======LEER =====")
    Dim Reader As TextReader
    Dim S As String
    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
    S = Reader.ReadAll
    Reader.Close
    Log("===========")
    Log(S)
End Sub

How I can put a Wait For it? Same example, please?
 
Upvote 0

Andrew (Digitwell)

Well-Known Member
Licensed User
Longtime User
Sleep is not a safe way to solve this. You just need to Wait for DownloadFile

You need to Wait for DownloadFile to complete.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    wait for (DownloadFile) complete (success as boolean)
    if (success) then
        leer
    end if
   
End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub DownloadFile as resumablesub
    'download csv file
    private success as boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    success = j.success
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    return success
End Sub


Sub

edit: for spelling
 
Upvote 0

jvrh_1

Active Member
Licensed User
Sleep is not a safe way to solve this. You just need to Wait for DownloadFile

You need to Wait for DownloadFile to complete.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    wait for (DownloadFile) complete (success as boolean)
    if (success) then
        leer
    end if
 
End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub DownloadFile as resumablesub
    'download csv file
    private success as boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    success = j.success
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    return success
End Sub


Sub

edit: for spelling
Sleep(0) Did not work. But the Wait For got an error too...

This is the new code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    wait for (DownloadFile) compelete (success As Boolean)
    If (success) Then
        leer
    End If
End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub DownloadFile()
    'download csv file
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
   
End Sub


Sub leer
    Log("=======LEER =====")
    Dim Reader As TextReader
    Dim S As String
    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
    S = Reader.ReadAll
    Reader.Close
    Log("===========")
    Log(S)
End Sub
 

Attachments

  • error.png
    error.png
    20 KB · Views: 105
Upvote 0

jvrh_1

Active Member
Licensed User
Do you see all the files in Log(j.GetString)?
When I do Log Log(j.GetString) I get this message (image attached). Only 18 rows again.

If I change leer to this, I get the same result:

B4X:
Sub leer1
    Log("=======LEER 1=====")
    Dim List1 As List
    List1 = File.ReadList(File.DirInternal, "datos.csv")
    For i = 1 To List1.Size - 1
        Log(List1.Get(i))
    Next
End Sub
 

Attachments

  • logs.png
    logs.png
    15.9 KB · Views: 102
Upvote 0

jvrh_1

Active Member
Licensed User
I have put a timer to read the .csv after 20 second. So, I do a new read after this time to have enought time to download the full file but, I get the same result:

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Dim t As Timer

End Sub
Sub t_tick()
    leer
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    t.Initialize("t",20000)
    t.Enabled=True
    DownloadFile


End Sub



Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub DownloadFile()
    'download csv file
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        'Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
End Sub


Sub leer
    Log("=======LEER =====")
    Dim Reader As TextReader
    Dim S As String
    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
    S = Reader.ReadAll
    Reader.Close
    Log("===========")
    Log(S)
End Sub

Thank you for all. I have not got more ideas. Help please...
 
Upvote 0

emexes

Expert
Licensed User
I have not got more ideas. Help please...

How about this? :
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
 
    wait for (DownloadFile) complete (success As Boolean)
    If (success) Then
        leer
    End If
  
End Sub


Sub Activity_Resume
End Sub


Sub Activity_Pause (UserClosed As Boolean)
End Sub


Sub DownloadFile() As ResumableSub
    'download csv file
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download("https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/export?format=csv")
    Wait For (j) JobDone(j As HttpJob)
    Dim SuccessFlag As Boolean = j.Success
    Log(SuccessFlag)
    If SuccessFlag Then
        '''Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    Return SuccessFlag
End Sub


Sub leer
    Log("=======LEER =====")
    Dim Reader As TextReader
    Dim S As String
    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
    S = Reader.ReadAll
    Reader.Close
    Log("===========")
    '''Log(S)

    'there are three commonly-used line separators: CR, LF, and CR+LF
    'these two .Replaces will standardise S to use LF as the line separator
    'LF is ASCII 10d = Chr(10); CR is ASCII 13d = Chr(13)
    S = S.Replace(Chr(13) & Chr(10), Chr(10))
    S = S.Replace(Chr(13), Chr(10))
  
    Dim L() As String = Regex.Split("\n", S)    'split into lines (around line separator \n = Chr(10))
    Dim NumLines As Int = L.Length
    Log("NumLines = " & NumLines)
  
    For I = 0 To NumLines - 1
        Dim F() As String = Regex.Split(",", L(I))    'split into fields (around field separator ",")
        Dim NumFields As Int = F.Length
        Log("NumFields = " & NumFields)
      
        For J = 0 To NumFields - 1
            Log("L(" & I & ") F(" & J & ") = """ & F(J) & """")
          
            If J = 0 Then
                Dim Ordinal() As String = Array As String("First", "Second", "Third", "Fourth")
              
                Dim P() As String = Regex.Split(" y ", F(0))
                For K = 0 To P.Length - 1    'Fortran Forever 🤣 
                    Log(Ordinal(K) & " player is """ & P(K) & """")
                Next
            End If
        Next
    Next
  
End Sub

Log output:
Logger connected to:  HMD Global Nokia C01 Plus
--------- beginning of system
--------- beginning of main
...
true
=======LEER =====
===========
NumLines = 28
NumFields = 2
L(0) F(0) = "Rubén y Krikri"
First player is "Rubén"
Second player is "Krikri"
L(0) F(1) = "2"
NumFields = 2
L(1) F(0) = "Javi y Krikri"
First player is "Javi"
Second player is "Krikri"
L(1) F(1) = "0"
NumFields = 2
L(2) F(0) = "Ferrer y Krikri"
First player is "Ferrer"
Second player is "Krikri"
L(2) F(1) = "1"
NumFields = 2
L(3) F(0) = "Álvaro y Krikri"
First player is "Álvaro"
Second player is "Krikri"
L(3) F(1) = "0"
NumFields = 2
L(4) F(0) = "Carlos y Krikri"
First player is "Carlos"
Second player is "Krikri"
L(4) F(1) = "0"
NumFields = 2
L(5) F(0) = "Oliver y Krikri"
First player is "Oliver"
Second player is "Krikri"
L(5) F(1) = "0"
NumFields = 2
L(6) F(0) = "Chusda y Krikri"
First player is "Chusda"
Second player is "Krikri"
L(6) F(1) = "1"
NumFields = 2
L(7) F(0) = "Javi y Rubén"
First player is "Javi"
Second player is "Rubén"
L(7) F(1) = "0"
NumFields = 2
L(8) F(0) = "Ferrer y Rubén"
First player is "Ferrer"
Second player is "Rubén"
L(8) F(1) = "0"
NumFields = 2
L(9) F(0) = "Álvaro y Rubén"
First player is "Álvaro"
Second player is "Rubén"
L(9) F(1) = "1"
NumFields = 2
L(10) F(0) = "Carlos y Rubén"
First player is "Carlos"
Second player is "Rubén"
L(10) F(1) = "0"
NumFields = 2
L(11) F(0) = "Oliver y Rubén"
First player is "Oliver"
Second player is "Rubén"
L(11) F(1) = "0"
NumFields = 2
L(12) F(0) = "Chusda y Rubén"
First player is "Chusda"
Second player is "Rubén"
L(12) F(1) = "0"
NumFields = 2
L(13) F(0) = "Ferrer y Javi"
First player is "Ferrer"
Second player is "Javi"
L(13) F(1) = "0"
NumFields = 2
L(14) F(0) = "Álvaro y Javi"
First player is "Álvaro"
Second player is "Javi"
L(14) F(1) = "2"
NumFields = 2
L(15) F(0) = "Carlos y Javi"
First player is "Carlos"
Second player is "Javi"
L(15) F(1) = "0"
NumFields = 2
L(16) F(0) = "Oliver y Javi"
First player is "Oliver"
Second player is "Javi"
L(16) F(1) = "0"
NumFields = 2
L(17) F(0) = "Chusda y Javi"
First player is "Chusda"
Second player is "Javi"
L(17) F(1) = "0"
NumFields = 2
L(18) F(0) = "Álvaro y Ferrer"
First player is "Álvaro"
Second player is "Ferrer"
L(18) F(1) = "0"
NumFields = 2
L(19) F(0) = "Carlos y Ferrer"
First player is "Carlos"
Second player is "Ferrer"
L(19) F(1) = "0"
NumFields = 2
L(20) F(0) = "Oliver y Ferrer"
First player is "Oliver"
Second player is "Ferrer"
L(20) F(1) = "0"
NumFields = 2
L(21) F(0) = "Chusda y Ferrer"
First player is "Chusda"
Second player is "Ferrer"
L(21) F(1) = "0"
NumFields = 2
L(22) F(0) = "Carlos y Álvaro"
First player is "Carlos"
Second player is "Álvaro"
L(22) F(1) = "1"
NumFields = 2
L(23) F(0) = "Oliver y Álvaro"
First player is "Oliver"
Second player is "Álvaro"
L(23) F(1) = "0"
NumFields = 2
L(24) F(0) = "Chusda y Álvaro"
First player is "Chusda"
Second player is "Álvaro"
L(24) F(1) = "0"
NumFields = 2
L(25) F(0) = "Oliver y Carlos"
First player is "Oliver"
Second player is "Carlos"
L(25) F(1) = "0"
NumFields = 2
L(26) F(0) = "Chusda y Carlos"
First player is "Chusda"
Second player is "Carlos"
L(26) F(1) = "0"
NumFields = 2
L(27) F(0) = "Chusda y Oliver"
First player is "Chusda"
Second player is "Oliver"
L(27) F(1) = "0"
** Activity (main) Pause, UserClosed = false **
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
How about this? :

The key changes I can remember making that made it work were:

+ the Resumable Sub with return status per https://www.b4x.com/android/forum/threads/download-and-read-csv.143351/#post-908298
+ changing the Google Sheet link from edit to download csv
+ using HttpJob .Download rather than .Download2, and relying on Google to return csv per request
+ changing the line separators from (I think) CR LF to be just LF (to match regex \n)

and then, as a no-extra-charge bonus, I parsed your csv into lines, the lines into fields, and the first field into players. 🍻
 
Upvote 0

emexes

Expert
Licensed User
+ changing the line separators from (I think) CR LF to be just LF (to match regex \n)

I am 50:50 as to whether this should be done before or after writing the download to the file.

On the one hand, it's nice if the file is precisely what was downloaded, warts and all.
On the other hand, it'd be nice if the file matched local convention so that it can be used without hassle by other programs.
 
Upvote 0

jvrh_1

Active Member
Licensed User
The key changes I can remember making that made it work were:

+ the Resumable Sub with return status per https://www.b4x.com/android/forum/threads/download-and-read-csv.143351/#post-908298
+ changing the Google Sheet link from edit to download csv
+ using HttpJob .Download rather than .Download2, and relying on Google to return csv per request
+ changing the line separators from (I think) CR LF to be just LF (to match regex \n)

and then, as a no-extra-charge bonus, I parsed your csv into lines, the lines into fields, and the first field into players. 🍻
Firstly, Thanks you Emexes, Mcqueccu and Andrew.
Emexes, thanks for you help. The . csv file is not the definitive one. It is actually a file linked to another Google Sheets sheet with the "IMPORTRANGE" function. I have tried your solution with the final file and it works perfectly. I would never have come up with all the solutions you propose. Thank you for your excellent work. You saved me.
 
Upvote 0

Knoppi

Active Member
Licensed User
Longtime User
look at post#5
B4X:
wait for (DownloadFile) complete (success as boolean)

you wrote post#7
B4X:
wait for (DownloadFile) compelete (success As Boolean)

I tested your code with the change and it worked
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    wait for (DownloadFile) complete (success As Boolean)
    If (success) Then
        leer
    End If
End Sub

Sub DownloadFile As ResumableSub
    'download csv file
    Private success As Boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    success = j.success
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    Return success
End Sub


Sub leer
    Log("=======LEER =====")
    Dim S As String = File.ReadString( File.DirInternal, "datos.csv")
'    Dim Reader As TextReader
'    Dim S As String
'    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
'    S = Reader.ReadAll
'    Reader.Close
    Log("===========")
    Log(S)
End Sub
 
Upvote 0

jvrh_1

Active Member
Licensed User
look at post#5
B4X:
wait for (DownloadFile) complete (success as boolean)

you wrote post#7
B4X:
wait for (DownloadFile) compelete (success As Boolean)

I tested your code with the change and it worked
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    wait for (DownloadFile) complete (success As Boolean)
    If (success) Then
        leer
    End If
End Sub

Sub DownloadFile As ResumableSub
    'download csv file
    Private success As Boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2($"https://docs.google.com/spreadsheets/d/1ZXx9s0yrOPZhX3GtlQgtcG7gvP6nqT74eJqiEv5H2qo/edit?usp=sharing"$, _
     Array As String("mimeType", "text/csv"))
    Wait For (j) JobDone(j As HttpJob)
    success = j.success
    If j.Success Then
        Log(j.GetString)
        Dim out As OutputStream = File.OpenOutput(File.DirInternal, "datos.csv", False)
        File.Copy2(j.GetInputStream, out)
        out.Close '<------ very important
    End If
    j.Release
    Return success
End Sub


Sub leer
    Log("=======LEER =====")
    Dim S As String = File.ReadString( File.DirInternal, "datos.csv")
'    Dim Reader As TextReader
'    Dim S As String
'    Reader.Initialize(File.OpenInput(File.DirInternal, "datos.csv"))
'    S = Reader.ReadAll
'    Reader.Close
    Log("===========")
    Log(S)
End Sub
Ohhhhh! I do not believe it. Complete by "complelete". I did a big mistake.😞😖😩.
Thank you again.
 
Upvote 0

johnmie

Active Member
Licensed User
Longtime User
Hello!
I have a problem with my App. It is very simple:

1- Download a Google Sheet (public).
2- Read data.


Dear jvrh_1
I've just completed a very small app in B4J (attached) to load and convert a *,csv file sent by my bank, it may help achieve what you want to do.
It is launched from an Excel-macro with Shell "C:\Program Files\USER\CSV Reader\CSVreader.exe", vbNormalFocus that waits for the copy to complete, then pastes it in the active worksheet,
The reason is that A) it is easier and faster than opening another Worksheet, B) I don't need all columns, C) the date format is not recognized as such by Excel and cannot be used for sorting, D) the number format is treated as text and cannot be used for calculations (' as 1000 separator removed).

Of course all of this could also be accomplished in an Excel macro, but B4J was easier.

It lets you search for *.csv files in the Windows Download path, does all the required conversions and then copies the result to the clipboard.
It closes itself after 2 minutes, just in case the user forgets to do so, also useful in case you want to run it in the background only.

Hope you find some of it useful.

Best, john m.
 
Upvote 0
Top