12

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

6
  • 1
    using this library CHCSVParser it's really easy to create a csv Commented Apr 26, 2019 at 14:57
  • Is it already in the swift library that can be directly imported? Commented Apr 26, 2019 at 15:00
  • nope you should add it to to your podfile in this way: pod 'CHCSVParser' Commented Apr 26, 2019 at 15:01
  • Wow, thanks! I will do some research on how to use CocoaPods later. I am new in Swift and I didn't know CocoaPods before. Commented Apr 26, 2019 at 15:05
  • use this guide, it's pretty simple: raywenderlich.com/… Commented Apr 26, 2019 at 15:07

2 Answers 2

19

Tutorial copied from https://iostutorialjunction.com/2018/01/create-csv-file-in-swift-programmatically.html:

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

    }
 }
Sign up to request clarification or add additional context in comments.

5 Comments

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?
you forgot the ! at the end to remove optional csvString = csvString.appending("(String(describing: dct["T"]!)), (String(describing: dct["F"]!))\n")
Oh right, thanks! But why all the 0 is under Time, instead of Force, where it is supposed to be
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
where could we find the file? I can't see it in Files app
3

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

1 Comment

where could we find the file? I can't see it in Files app

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.