Can I import data from CSV into SwiftData?

I’m making a table of tunes with several columns (so far just using strings but will eventually include audio players and links to images).

At this point I just have a simple UI to enter field data into SwiftData and sort it by either tune name or key. I’ll add the other columns and functionality later.

I currently have an excel file with over 200 rows. Is there a way to import that data into my SwiftData db so I don’t have to type in all that data as individual items?

@BarbE

Hi Barb,

Welcome to the community.

Yes you can, but it’s a bit of work.

As a suggested first step, you need to export the data from Excel as a CSV file and configure the export to separate each row of data with a comma as a delimiter between each column. You can then drag the file into your Xcode File Navigator panel on the left so that is part of the Bundle. Let’s say you called the file “data.csv”

You can then open that file and import the entire file as a String which you can then separate into an array of rows by using the “\n” line terminator character as the delimiter which should give an array with the more than 200 rows you referred to above. Are you still with me?

You then loop through the array of rows and split each row into an array of columns delimited by the comma character which you specified when exporting the data from Excel. Each element of the array of columns will be a String. Have I lost you yet?

Since you now have the row spit into an array of columns, you can create an instance of your SwiftData model and then reference each element of the array of columns and match that to the relevant SwiftData attribute.

Does that make sense?

If you can provide me a sample of your data I can write some code to do what you want it to do.

Just got back to my machine… I think I get it and want to give it a try on my own, but if I get stuck I’ll holler back. Thank you SO much!

OK, I’m confused. Lots I don’t know here. Let’s start here:

When I add the csv to the nav, does it go here? (I’ve named it TestTuneCsv)
image

How do I “import the entire file as a string”?

Here’s some data… some fields are empty which explains all the commas:

Key,Tune,Notes,Mp3,Chart,Source,Status\n

C,Acrobat’s New Trick,Frank Blade,Love\n

D,Across the Sea,No G - long pause,Isham Monday,\n

C,Altamont,John Lusk,\n

A,Ball and Chain Hornpipe,Kenny Baker,Meh\n

When you create a csv version of your Excel data file is should save that with a file extension of .csv. It could be that your Mac is configured to not show the file extensions (that’s the default) on any file but it’s there even if you can’t see it.

The extension identifies the file type so that the operating system knows how to deal with them.

To see it, in Finder, select the file and then right click and select “Get Info”. You should see the

To change the settings on your Mac so that all file extensions are visible, see this link.

Take note of the warning about changing a file extension name because it could mean that the file is no longer readable.

Text files have a extension of .txt
JPG images have an extension of .jpg
In Xcode your ContentView has a file extension of .swift

I made an assumption that you were aware that a text file has an invisible carriage return or line terminator for each line of text. It’s there but you can’t see it so there is no need to add it to each line.

There appears to be some inconsistencies with the sample data in that if there are any columns that have no data then your csv file should show a line where there are two or more commas in succession.

In other words there should be exactly the same number of separators for each row irrespective if there is or is not data in a specific column.

Lets say you had a transaction file downloaded from your bank where you had this kind of layout:

Date,Debit,Credit,Balance,Description
11/8/2008,,1753.98,2875.77,PAYMENT THANKYOU
5/8/2008,115,,4629.75,GROCERIES

In the case of a credit transaction there would be two commas just prior as in the first transaction and in the case of a debit there would be two commas just after.

To process that csv file I created a function to do so and created a dataModel to mirror the transaction structure.

struct Transaction: Identifiable {
    var id = UUID()
    var date: String
    var debit: Double
    var credit: Double
    var balance: Double
    var description: String
}

My ViewModel where the data is processed:

@Observable
class ViewModel {
    var transactions = [Transaction]()

    func getTransactions() {
        let url = Bundle.main.url(forResource: "anz", withExtension: "csv")
        if let url {
            do {
                let data = try String(contentsOf: url)
                let allRecords = Array(data.components(separatedBy: "\r\n")) // \r\n means carriage return and line feed which I needed to use in this case
                var records = Array(allRecords.dropFirst()) // Remove the header record
                records = records.dropLast() // Removes the last record which is blank

                for record in records {
                    let columns = Array(record.components(separatedBy: ","))
                    let newTransaction = Transaction(date: columns[0], debit: Double(columns[1]) ?? 0.0, credit: Double(columns[2]) ?? 0.0, balance: Double(columns[3]) ?? 0.0, description: columns[4])
                    transactions.append(newTransaction)
                }
                print(transactions)

            } catch {
                print(error.localizedDescription)
            }

        }
    }
}

I hope that gives you some idea of how to process your own csv file.