Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a CSV file using Swift

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

like image 382
Fëanor Tang Avatar asked Apr 26 '19 14:04

Fëanor Tang


2 Answers

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")
        }

    }
 }
like image 103
Rahmouni Rabii Avatar answered Oct 04 '22 23:10

Rahmouni Rabii


Excellent answer above, made a slight modification to address specific instances in the data. You can modify individual components as needed and remove commas, trim UUIDs, etc. Note this solution uses transactions stored in a list of Core Data objects. I also print the location of the data file so you can check it in the simulator.

  func createCSVFile() {
        var csvString = "id,name,description,category,date,type,receipt,amount\n"
        for trans in transactions {
            let transID = trans.id!.debugDescription.split(separator: "-")[0].replacingOccurrences(of: ")", with: "")
            let transName = trans.name!
            let transDesc = trans.desc!.replacingOccurrences(of: ",", with: "-")
            let transCat = trans.category!
            let transDate = trans.date!
            let transType = trans.type!
            
            var transReceipt = "None"
            if trans.receipt == nil {
                transReceipt = "Present"
            }
            let transAmount = trans.amount
            let dataString = "\(transID),\(transName),\(transDesc),\(transCat),\(transDate),\(transType),\(transReceipt),\(transAmount)\n"
            print("DATA: \(dataString)")
            csvString = csvString.appending(dataString)
        }

        let fileManager = FileManager.default
        do {
            let path = try fileManager.url(for: .documentDirectory, in: .allDomainsMask, appropriateFor: nil, create: false)
            print("PATH: \(path)")
            let fileURL = path.appendingPathComponent("CSVData.csv")
            try csvString.write(to: fileURL, atomically: true, encoding: .utf8)
        } catch {
            print("error creating file")
        }
    }
like image 40
RandallShanePhD Avatar answered Oct 04 '22 22:10

RandallShanePhD