2016-01-24 115 views
0

我正在保存CSV文件并通过电子邮件发送。它可以工作,但CSV格式不正确。应该移动到新行的一些项目包含在现有行的第二列中。有5列,id,名称,型号,ups和价格。有什么我创建文件时做错了吗?CSV格式不正确

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

enter image description here

回答

1

这条线:

let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i]) 

是您正在使用创建CSV文件的每一行的内容。这只适用于简单的情况。

下面是CSV规则:

  1. 如果字段值包含字段分隔符(逗号你的情况),报价,空格处的值的任一端,或任何换行符的字段值必须用引号括起来(通常用双引号)。
  2. 如果字段值包含任何引号字符,则必须用另一引号字符转义每个引号字符。

创建和解析CSV文件比大多数人意识到的要复杂得多。

要么修改您的逻辑来添加任何所需的引用或找到正确处理所有这些情况的第三方CSV库。