How to create a CSV file using Swift

10,231

Step 1:

Create an array, named as "employeeArray" which will store all our records for the employees as key value objects. Also we will add dummy data to the newly created array

class ViewController: UIViewController {
 var employeeArray:[Dictionary<String, AnyObject>] =  Array()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
   for i in 1...10 {
            var dct = Dictionary<String, AnyObject>()
            dct.updateValue(i as AnyObject, forKey: "EmpID")
            dct.updateValue("NameForEmplyee id = \(i)" as AnyObject, forKey: "EmpName")
            employeeArray.append(dct)
        }
    }
}

Step 2: Now we have data with us, and its time to create CSV(comma separated values) file using swift programmatically. For this we will loop through our records in "employeeArray" and append them in a string. Then we will write this string to our document directory of the app. All the stuff goes in different function named as "createCSV", below is the code for the same

func createCSV(from recArray:[Dictionary<String, AnyObject>]) {
        var csvString = "\("Employee ID"),\("Employee Name")\n\n"
        for dct in recArray {
            csvString = csvString.appending("\(String(describing: dct["EmpID"]!)) ,\(String(describing: dct["EmpName"]!))\n")
        }

        let fileManager = FileManager.default
        do {
            let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
            let fileURL = path.appendingPathComponent("CSVRec.csv")
            try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
        } catch {
            print("error creating file")
        }

    }

Step 3: Finally we will call our function from "viewDidLoad". Below is the complete code

class ViewController: UIViewController {
 var employeeArray:[Dictionary<String, AnyObject>] =  Array()

    override func viewDidLoad() {
        super.viewDidLoad()
         for i in 1...10 {
                   var dct = Dictionary<String, AnyObject>()
                   dct.updateValue(i as AnyObject, forKey: "EmpID")
                   dct.updateValue("NameForEmplyee id = \(i)" as AnyObject, forKey: "EmpName")
                   employeeArray.append(dct)
               }

               createCSV(from: employeeArray)

    }

 func createCSV(from recArray:[Dictionary<String, AnyObject>]) {
        var csvString = "\("Employee ID"),\("Employee Name")\n\n"
        for dct in recArray {
            csvString = csvString.appending("\(String(describing: dct["EmpID"]!)) ,\(String(describing: dct["EmpName"]!))\n")
        }

        let fileManager = FileManager.default
        do {
            let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
            let fileURL = path.appendingPathComponent("CSVRec.csv")
            try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
        } catch {
            print("error creating file")
        }

    }
 }
Share:
10,231
Fëanor Tang
Author by

Fëanor Tang

Updated on June 07, 2022

Comments

  • Fëanor Tang
    Fëanor Tang over 1 year

    In an app I created to collect data from Apple pencil input, I tried to export the data into a CSV file. But so far, I only managed to create a single column which records the time length. I want to add another column to record the force from the Apple pencil.

    This is what I have tried to do:

    var patientsData:[Dictionary<String, AnyObject>] = Array()
    var dct = Dictionary<String, AnyObject>()
    
    // MARK: CSV writing
    func createCSVX(from recArray:[Dictionary<String, AnyObject>]) {
    var csvString = "\("Time")\n"
    dct.updateValue(TestDraw.time as AnyObject, forKey: "T")
    csvString = csvString.appending("\(String(describing: dct["T"]))\n")
    patientsData.append(dct)
    let fileManager = FileManager.default
    do {
        let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
        let fileURL = path.appendingPathComponent("TrailTime.csv")
        try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
    } catch {
        print("error creating file")
        }
    
    }
    

    I know I can write another function to create another CSV file with a single column to record the force, but I would like to record them in a single spreadsheet​.

    Also, does anyone know how to remove the "Optional" in the CSV file created?

    This is what I have tried based on one of the answers.

    func createCSVX(from recArray:[Dictionary<String, AnyObject>]) {
    var csvString = "\("Time"),\("Force")\n"
    
    dct.updateValue(TestDraw.time as AnyObject, forKey: "T")
    
    dct.updateValue(TestDraw.force as AnyObject, forKey: "F")
    
    patientsData.append(dct)
    
    csvString = csvString.appending("\(String(describing: dct["T"])), \(String(describing:   dct["F"]))\n")
    
    let fileManager = FileManager.default
    
    do {
    
    let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil , create: false )
    
    let fileURL = path.appendingPathComponent("TrailTime.csv")
    
    try csvString.write(to: fileURL, atomically: true , encoding: .utf8)
    } catch {
    
    print("error creating file")
    
    }
    
    print(TestDraw.force)
    
    }
    

    Screeshot of the exported CSV file

  • Fëanor Tang
    Fëanor Tang over 4 years
    I have tried what you suggested, but unfortunately, the data in Force all go​ into the Time column. Would you please take a look at the change I made in the original question and point out what goes wrong?
  • Rahmouni Rabii
    Rahmouni Rabii over 4 years
    you forgot the ! at the end to remove optional csvString = csvString.appending("(String(describing: dct["T"]!)), (String(describing: dct["F"]!))\n")
  • Fëanor Tang
    Fëanor Tang over 4 years
    Oh right, thanks! But why all the 0 is under Time, instead of Force, where it is supposed to be
  • Protocol
    Protocol about 3 years
    from above csv is comma separated file. But if any string is itself contains comma then this fails. Please suggest any way to overcome that
  • user4150758
    user4150758 almost 2 years
    where could we find the file? I can't see it in Files app
  • user4150758
    user4150758 almost 2 years
    where could we find the file? I can't see it in Files app