6

I'm building an app with core data (1 entity with 5 attributes) that display in a tableView. Now i would like to export this data to a CSV file (so i can send this file with mail from phone) so i can open it in excel on a windows. i search a lot but didn't find the right answer. Can someone help me or give me a link to a good explanation or tutorial?

I'm building in swift btw.

func createExportString() -> String {
    var merk: String?
    var ref: String?
    var beschrijving: String?
    var aantal: String?
    var wbs: String?

    var export = NSLocalizedString("merk, ref, beschrijving, aantal, wbs \n", comment: "")
            merk = Lijst.valueForKey("merk") as? String
            ref = Lijst.valueForKey("ref") as? String
            aantal = Lijst.valueForKey("aantal") as? String
            beschrijving = Lijst.valueForKey("beschrijving") as? String
            wbs = Lijst.valueForKey("wbs") as? String


            let merkString = "\(merk!)" ?? "-"
            let refString = "\(ref!)" ?? "-"
            let beschString = "\(beschrijving!)" ?? "-"
            let aantalString = "\(aantal!)" ?? "-"
            let wbsString = "\(wbs!)" ?? "-"

            export += merkString + "," + refString + "," + beschString + "," + aantalString +
                "," + wbsString + "\n"

    print("This is what the app will export: \(export)")
    return export
}

@IBAction func saveToCSV(sender: AnyObject) {
    exportDatabase()
}

func exportDatabase() {
    var exportString = createExportString()
    saveAndExport(exportString)
}

func saveAndExport(exportString: String) {
    let exportFilePath = NSTemporaryDirectory() + "export.csv"
    let exportFileURL = NSURL(fileURLWithPath: exportFilePath)
    NSFileManager.defaultManager().createFileAtPath(exportFilePath, contents: NSData(), attributes: nil)
    var fileHandleError: NSError? = nil
    var fileHandle: NSFileHandle? = nil
    do {
        fileHandle = try NSFileHandle(forWritingToURL: exportFileURL)
    } catch {
        print( "Error with fileHandle")
    }

    if fileHandle != nil {
        fileHandle!.seekToEndOfFile()
        let csvData = exportString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        fileHandle!.writeData(csvData!)

        fileHandle!.closeFile()

        let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
        let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)

        self.presentViewController(activityViewController, animated: true, completion: nil)
    }
}
6
  • Check stackoverflow.com/questions/10572172/… Commented Feb 20, 2016 at 23:48
  • @UlyssesR i already came to that one, but i'm just a beginner and don't really have an idea on how to convert obejctive-c to swift... Commented Feb 21, 2016 at 0:03
  • Maybe this step by step video help you, youtube.com/watch?v=iBZbMkmtHuU Commented Feb 21, 2016 at 0:05
  • @UlyssesR already did that video to :p, i've imported that with my data into my app but i'm getting error's on the createExportString function. Commented Feb 21, 2016 at 0:07
  • Can you put the code and the error? may help us to debug the code. Commented Feb 21, 2016 at 0:09

1 Answer 1

9

This is a concise way of doing all you want - you pass array of managed objects and a string that is CSV's filename. The method writes your CSV to a file. I believe you already have most of this in your code, the thing that is lacking are last two lines that just write a string into a new file in "Documents" directory.

func writeCoreDataObjectToCSV(objects: [NSManagedObject], named: String) -> String? {
    /* We assume that all objects are of the same type */
    guard objects.count > 0 else {
        return nil
    }
    let firstObject = objects[0]
    let attribs = Array<Any>(firstObject.entity.attributesByName.keys)
    let csvHeaderString = (attribs.reduce("",combine: {($0 as String) + "," + $1 }) as NSString).substringFromIndex(1) + "\n"

    let csvArray = objects.map({object in
        (attribs.map({(object.valueForKey($0) ?? "NIL").description}).reduce("",combine: {$0 + "," + $1}) as NSString).substringFromIndex(1) + "\n"
    })
    let csvString = csvArray.reduce("", combine: +)

    return csvHeaderString+csvString
}

Now, somewhere else in the code you need to create NSData from this string and add it to mail composer:

let csvString = .....
let data = csvString.dataUsingEncoding(NSUTF8StringEncoding)
let composer = MFMailComposeViewController()
composer.addAttachmentData(attachment: data,
          mimeType mimeType: "text/csv",
          fileName filename: "mydata.csv")

Then, do the usual stuff with the composer (set body, topic, etc) and present it to the user!

EDIT:

Edited the answer to better answer the question.

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

9 Comments

can you maybe give me some more explanation for this code? where do you put it in a file and where do you put this code in the viewcontroller?
Allright, my mistake. This does basically what let export = does. I'll edit the answer
ok. did u already edited your answer? i don't really see a difference? :p
ok i think i understand it? but where do i find the csv file then so i can use it?
DocumentsDir variable holds the exact path to your file. Maybe the name is a bit unfortunate :) You can return it from the function and then use it somewhere else (e.g. mail controller).
|

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.