Reputation: 3600
I am saving a CSV file and emailing it. It works but the CSV is not formatted correctly. Some of the items that should be moved to a new row are included the the second column of an existing row. There are 5 columns, id, name, model, ups, and price. Is there something I've done wrong when creating the file?
func openActions() {
actions = UIAlertController(title: "", message: "", preferredStyle: .ActionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: {
(action) -> Void in
self.actions?.dismissViewControllerAnimated(true, completion: nil)
})
let saveCSV = UIAlertAction(title: "Save as CSV", style: .Default, handler: {
(action) -> Void in
self.getAndSaveItems()
self.actions?.dismissViewControllerAnimated(true, completion: nil)
})
let viewFile = UIAlertAction(title: "View CSV", style: .Default, handler: {
(action) -> Void in
self.viewFile()
self.actions?.dismissViewControllerAnimated(true, completion: nil)
})
let emailFile = UIAlertAction(title: "Email CSV", style: .Default, handler: {
(action) -> Void in
self.emailFile()
self.actions?.dismissViewControllerAnimated(true, completion: nil)
})
actions?.addAction(cancelAction)
actions?.addAction(emailFile)
actions?.addAction(viewFile)
actions?.addAction(saveCSV)
self.presentViewController(actions!, animated: true, completion: nil)
}
func dataFilePath() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
let titleString = self.title!.stringByReplacingOccurrencesOfString(" ", withString: "_")
let string = String(format: "/%@.csv", titleString)
return documentsDirectory.stringByAppendingString(string)
}
func getAndSaveItems() {
let getLimit = 1000
var getSkip = 0
activityIndicator?.startAnimating()
let query = PFQuery(className: "Items")
query.whereKey("user", equalTo: PFUser.currentUser()!)
query.whereKey("collection", equalTo: self.title!)
query.orderByAscending("item")
query.limit = getLimit
query.skip = getSkip
query.findObjectsInBackgroundWithBlock( {
(objects, error) -> Void in
if error == nil {
if let objects = objects as [PFObject]! {
for object in objects {
self.names.append(object["item"] as! String)
self.upcs.append(object["upc"] as! String)
self.ids.append(object.objectId!)
self.models.append(object["model"] as! String)
self.prices.append(object["pricePaid"] as! String)
if object["notes"] == nil {
self.notes.append(nil)
} else {
self.notes.append(object["notes"] as? String)
}
}
}
if objects!.count == getLimit {
getSkip += getLimit
self.getAndSaveItems()
}
} else {
// Show error...
}
})
writeToFile()
}
func writeToFile() {
if (!NSFileManager.defaultManager().fileExistsAtPath(self.dataFilePath())) {
NSFileManager.defaultManager().createFileAtPath(self.dataFilePath(), contents: nil, attributes: nil)
}
// var writeString = NSMutableString(capacity: 0)
var writeString = String()
writeString.reserveCapacity(0)
for (var i = 0; i < names.count; i++) {
let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i])
writeString.appendContentsOf(stringToWrite)
}
let handle = NSFileHandle(forWritingAtPath: self.dataFilePath())
handle?.truncateFileAtOffset((handle?.seekToEndOfFile())!)
handle?.writeData(writeString.dataUsingEncoding(NSUTF8StringEncoding)!)
self.activityIndicator?.stopAnimating()
}
func viewFile() {
if (NSFileManager.defaultManager().fileExistsAtPath(dataFilePath())) {
let fileData = NSData(contentsOfFile: dataFilePath())
let fileVC = FileViewController(nibName: "FileViewController", bundle: nil)
let navController = NavController(rootViewController: fileVC)
fileVC.fileData = fileData
self.presentViewController(navController, animated: true, completion: nil)
} else {
// File doesn't exist...
print("File doesn't exist")
}
}
func emailFile() {
if (NSFileManager.defaultManager().fileExistsAtPath(dataFilePath())) {
if MFMailComposeViewController.canSendMail() {
let mailComposer = MFMailComposeViewController()
mailComposer.mailComposeDelegate = self
let subject = String(format: "My %@ Collection", self.title!)
mailComposer.setSubject(subject)
mailComposer.setMessageBody("", isHTML: false)
let fileData = NSData(contentsOfFile: dataFilePath())
let titleString = self.title!.stringByReplacingOccurrencesOfString(" ", withString: "_")
let fileNameString = String(format: "%@.csv", titleString)
mailComposer.addAttachmentData(fileData!, mimeType: "text/csv", fileName: fileNameString)
self.presentViewController(mailComposer, animated: true, completion: nil)
} else {
// Can't send mail...
}
} else {
// File doesn't exist...
print("File doesn't exist")
}
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
self.dismissViewControllerAnimated(true, completion: nil)
}
Upvotes: 0
Views: 74
Reputation: 318804
This line:
let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i])
is what you are using to create each line of the CSV file. This will only work in simple cases.
Here are the CSV rules:
Creating and parsing CSV files is much more involved than most people realize.
Either modify your logic to add any needed quoting or find a 3rd party CSV library that properly handles all of these cases.
Upvotes: 1