Is there any way to export tablesorter table to excel? - tablesorter

I am using tablesorter library for displaying the table. Is there any feature in tablesorter for exporting table to excel?

// export excel & email
enter code here
#IBAction func exportAction(_ sender: UIButton) {
// Set the path to the path of wherever you put your Excel file.
// The path in this demo code is the path to the demo.xlsx file.
path = Bundle.main.path(forResource: "demo", ofType: "xlsx")!
// Open the spreadsheet, get the first sheet, first worksheet, and first cell A1.
// This is solely demoed code to show basics; your actual code would do much more here.
let spreadsheet: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(path)
let worksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0] as! BRAWorksheet
for row in 0..<self.data.count {
let producerName = self.data[row][0]
let clientName = self.data[row][1]
let revenue = self.data[row][2]
let date = self.data[row][3]
let aCell = "A" + "\(row+2)"
let bCell = "B" + "\(row+2)"
let cCell = "C" + "\(row+2)"
let dCell = "D" + "\(row+2)"
worksheet.cell(forCellReference: aCell, shouldCreate: true)?.setStringValue(producerName)
worksheet.cell(forCellReference: bCell, shouldCreate: true)?.setStringValue(clientName)
worksheet.cell(forCellReference: cCell, shouldCreate: true)?.setStringValue(revenue)
worksheet.cell(forCellReference: dCell, shouldCreate: true)?.setStringValue(date)
}
// save as demoAs.xlsx excel file
let paths: Array = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) as Array
let appendingStr = "/Report " + self.getTodayDateForExport() + ".xlsx"
let fullPath: String = (paths[0]).appendingFormat(appendingStr)
spreadsheet.save(as: fullPath)
path = fullPath
// Print some info to show the code works.
print("")
let fileURL = NSURL(fileURLWithPath: path!)
let activityVC = UIActivityViewController(activityItems: [fileURL as Any], applicationActivities: nil)
activityVC.popoverPresentationController!.sourceView = self.view
activityVC.completionWithItemsHandler = { activity, success, items, error in
if success {
self.view.makeToast("reported!")
} else {
self.view.makeToast("cancelled!")
}
}
self.present(activityVC, animated: true, completion: nil)
}

Related

UIDocumentInteractionController change file name for Sharing

iam using the following code to show the sharing options for PDF
self.documentController = UIDocumentInteractionController(url: url)
self.documentController.name = "Test name" // not working
self.documentController.presentOptionsMenu(from: self.shareButton, animated: true)
the problem is that I save the PDF file name with datestamp to avoid having two files with the same name, but when the share options is being shown the actual file name appears,
is there is a way to show custom name instead of the actual filename (I don't want to copy the file to other place and rename it, waste of time and performance)
In such a situation, we can create a temporary folder which can contain the same file with lastPathExtension will be document.fileExtension and we can pass this newly file path to UIDocumentInteractionController.init(url: newFileUrl)
For Example:
func openUnsupportedFileWithPath(documentName : String, fileurl : URL, fileExtension : String, aDocument: SILDocumentDB? = nil, sourceView: UIView? = nil) -> Void {
// Create new temporary path
let paths: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
var newFileUrl: String = paths.appending("/Downloads/TemporaryFolder)")
newFileUrl = newFileUrl.appendingFormat("%#","\(documentName)")
let destinationPathUrl : URL
do {
// Move newly filePath with new fileName and fileExtension
destinationPathUrl = URL(fileURLWithPath: destinanewFileUrltionPath)
try FileManager.default.moveItem(at: fileurl, to: destinationPathUrl)
} catch {
print(error)
}
//Pass newly filePath to UIDocumentInteractionController
documentInteractionController = UIDocumentInteractionController.init(url: newFileUrl)
documentInteractionController?.name = documentName
documentInteractionController?.delegate = self
let canPreview = documentInteractionController?.presentPreview(animated: true)
if (canPreview == false) {
let activityViewController = UIActivityViewController.init(activityItems: [fileurl], applicationActivities: nil)
activityViewController.setValue(documentName, forKey: "subject")
if ISIPAD {
activityViewController.popoverPresentationController?.sourceView = sourceView ?? self.view
}
self.present(activityViewController, animated: true, completion: nil)
}
}
And UIDocumentInteractionController get dismiss, remove the temporary filePath on documentInteractionControllerDidEndPreview(_ controller: UIDocumentInteractionController) method.
public func documentInteractionControllerDidEndPreview(_ controller: UIDocumentInteractionController) {
documentInteractionController = nil
let paths: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath: String = paths.appending("/Downloads/TemporaryFolder)")
let _fileManager : FileManager = FileManager.default
if filePath.length > 0 {
if _fileManager.fileExists(atPath: filePath) {
do{
try _fileManager.removeItem(atPath: filePath)
}catch let error as NSError{
print("\(error.localizedDescription)")
}
}
}
}

how to share QR created image swift 4

I am creating QR code in swift and assigning it to an imageView
when I try to share that image with generated code, it does not shares that image,
func createCode()
{
let text = email
let data = text.data(using: .ascii, allowLossyConversion: false)
fillter = CIFilter(name: "CIQRCodeGenerator")
fillter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 5.0, y: 5.0)
CreatedImage = UIImage(ciImage: (fillter.outputImage?.transformed(by: transform))!)
imageCode.image = CreatedImage as UIImage
}
and this is share button
#IBAction func shareButtonPressed(_ sender: Any)
{
let activityItem: [UIImage] = [imageCode.image!]
let activity = UIActivityViewController(activityItems: activityItem as [UIImage], applicationActivities: [])
activity.popoverPresentationController?.sourceView = self.view
self.present(activity, animated: true, completion: nil)
}
it shows like it has nothing to share, it does not pick any bit of image
Have you created a variable to store the image somewhere e.g.
var generatedImage: UIImage?
Assuming then, that I have read your question correctly, in your creation function you can cast the image at the end of the function e.g:
generatedImage = imageCode.image
Then in your share function you could say:
guard let validQR = generatedImage else { return }
let activityItem: [UIImage] = [validQR]
let activity = UIActivityViewController(activityItems: activityItem as [UIImage], applicationActivities: [])
activity.popoverPresentationController?.sourceView = self.view
self.present(activity, animated: true, completion: nil)
I tested with an image from my Bundle e.g:
generatedImage = UIImage(named: "SCNPyramid")
And I was able to share the image :)
after searching all..
I cam I to know that make a programmatically screen shot of desired view, that is sent..
I have been having the same problem and solved it by first saving the generated qr code image to a file and then sharing the file url.
private func shareQRCode() {
guard let qrcode = self.qrCodeImage,
let data = qrcode.pngData(),
let url = self.saveInCache(data: data, fileName: "QRCode.png") else { return }
// set up activity view controller
let imageToShare = [url]
let activityViewController = UIActivityViewController(activityItems: imageToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view // so that iPads won't crash
// work around to prevent dismissing current view after saving image
let tempController = TransparentViewController()
tempController.modalPresentationStyle = .overFullScreen
activityViewController.completionWithItemsHandler = { [weak tempController] _, _, _, _ in
if let presentingViewController = tempController?.presentingViewController {
presentingViewController.dismiss(animated: false, completion: nil)
} else {
tempController?.dismiss(animated: false, completion: nil)
}
}
present(tempController, animated: true) { [weak tempController] in
tempController?.present(activityViewController, animated: true, completion: nil)
}
}
Here is the code for saveInCache function:
private func saveInCache(data: Data, fileName: String) -> URL? {
let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
let path = paths[0]
let fileUrl = path.appendingPathComponent(fileName)
let fileManager = FileManager.default
if self.pathExists(fileUrl) {
do {
try fileManager.removeItem(at: fileUrl)
} catch { return fileUrl }
}
guard fileManager.createFile(atPath: fileUrl.path, contents: data, attributes: nil) else {
return nil
}
return fileUrl
}
private func pathExists(_ path: URL) -> Bool {
let fileManager = FileManager.default
var isDir: ObjCBool = false
if fileManager.fileExists(atPath: path.path, isDirectory: &isDir) {
if isDir.boolValue {
// file exists and is a directory
return true
} else {
// file exists and is not a directory
return true
}
} else {
// file does not exist
return false
}
}
And here a simple Transparent View Controller for ActivityViewController work around:
final class TransparentViewController: UIViewController {
override func viewDidLoad() {
self.view.backgroundColor = .clear
}
}

How to create vCard/vcf file to use in share sheet?

I'm new to swift and methods I am finding are deprecated regarding my issue. I'm building a directory app and I'm pulling contact data from an API, not from the phone's address book.
In iOS, if you go to your address book, you can select a contact and choose 'Share Contact' which brings up a share sheet. I want this exact functionality in my app.
I think I've got Share Sheets figured out, and here's my code for that:
#IBAction func actShare(sender: AnyObject) {
let activityViewController = UIActivityViewController(activityItems: ["text" as NSString], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: {})
}
I want to to change "text" as NSString to be a vCard, as that is the object that iOS shares from the address book, right? Assuming I'm right, I want to create a vCard from my own app's contact object in order to share it to appropriate apps (email, sms, etc).
How can I achieve that in Swift? If I'm wrong, please correct me and show me what I need to do. Thanks.
EDIT: Okay, here's my changes.
#IBAction func actShare(sender: AnyObject) {
do {
var contactData = NSData()
try contactData = CNContactVCardSerialization.dataWithContacts([createContact()])
let activityViewController = UIActivityViewController(activityItems: [contactData as NSData], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: {})
} catch {
print("CNContactVCardSerialization cannot save address")
}
and
func createContact() -> CNMutableContact {
let contactCard = CNMutableContact()
contactCard.givenName = "John"
contactCard.familyName = "Doe"
contactCard.emailAddresses = [
CNLabeledValue(label: CNLabelWork, value: "john.doe#email.com")
]
return contactCard
}
However, when I click the share button and it brings up my share sheet, I select the application I want to share to and it doesn't add/attach the contact data as intended. How do I accomplish this?
The trick here is to save the contact to a VCard (.vcf) file using CNContactVCardSerialization.dataWithContacts, then pass the file URL to the UIActivityViewController. The activity view controller detects the VCard format from the file extension, and shows the apps where the format is supported (e.g. Messages, Mail, Notes, Airdrop, etc)
Example:
#IBAction func buttonTapped(button: UIButton) {
let contact = createContact()
do {
try shareContacts([contact])
}
catch {
// Handle error
}
}
func shareContacts(contacts: [CNContact]) throws {
guard let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first else {
return
}
var filename = NSUUID().UUIDString
// Create a human friendly file name if sharing a single contact.
if let contact = contacts.first where contacts.count == 1 {
if let fullname = CNContactFormatter().stringFromContact(contact) {
filename = fullname.componentsSeparatedByString(" ").joinWithSeparator("")
}
}
let fileURL = directoryURL
.URLByAppendingPathComponent(filename)
.URLByAppendingPathExtension("vcf")
let data = try CNContactVCardSerialization.dataWithContacts(contacts)
print("filename: \(filename)")
print("contact: \(String(data: data, encoding: NSUTF8StringEncoding))")
try data.writeToURL(fileURL, options: [.AtomicWrite])
let activityViewController = UIActivityViewController(
activityItems: [fileURL],
applicationActivities: nil
)
presentViewController(activityViewController, animated: true, completion: {})
}
func createContact() -> CNContact {
// Creating a mutable object to add to the contact
let contact = CNMutableContact()
contact.imageData = NSData() // The profile picture as a NSData object
contact.givenName = "John"
contact.familyName = "Appleseed"
let homeEmail = CNLabeledValue(label:CNLabelHome, value:"john#example.com")
let workEmail = CNLabeledValue(label:CNLabelWork, value:"j.appleseed#icloud.com")
contact.emailAddresses = [homeEmail, workEmail]
contact.phoneNumbers = [CNLabeledValue(
label:CNLabelPhoneNumberiPhone,
value:CNPhoneNumber(stringValue:"(408) 555-0126"))]
return contact
}
You may use a CNContact (requires iOS 9):
let contact = CNMutableContact()
contact.givenName = "John"
contact.familyName = "Doe"
contact.emailAddresses = [
CNLabeledValue(label: CNLabelWork, value: "john.doe#email.com")
]
It is very simple to create contact from your iOS app and share over
the external apps.
First you need to create Share Button Action like below :-
-(void)shareContactAction:(UIButton*)sender
{
CNMutableContact *selectedCon = [[CNMutableContact alloc] init];
selectedCon.givenName = #"ABC";
selectedCon.familyName = #"XYZ";
NSString *phoneNum = #"+91-XXXXXXXXXXX"
CNLabeledValue *contactNum1 = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:[CNPhoneNumber phoneNumberWithStringValue:phoneNum]];
selectedCon.phoneNumbers = #[contactNum1];
NSString *url=[self saveContactDetailsToDocDir:selectedCon];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[#"Contact", [NSURL fileURLWithPath:url]] applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
}
Than you can call the function below which will return the path of the
contact card in above button event.
- (NSString *)saveContactDetailsToDocDir:(CNContact *)contact {
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString * contactCardPath = [documentsDirectory stringByAppendingString:#"/vCardName.vcf"];
NSArray *array = [[NSArray alloc] initWithObjects:contact, nil];
NSError *error;
NSData *data = [CNContactVCardSerialization dataWithContacts:array error:&error];
[data writeToFile:contactCardPath atomically:YES];
return contactCardPath;
}
Updated for Swift 4:
#IBAction func buttonTapped(button: UIButton) {
let contact = createContact()
do {
try shareContacts(contacts: [contact])
}
catch {
// Handle error
}
}
func shareContacts(contacts: [CNContact]) throws {
guard let directoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return
}
var filename = NSUUID().uuidString
// Create a human friendly file name if sharing a single contact.
if let contact = contacts.first, contacts.count == 1 {
if let fullname = CNContactFormatter().string(from: contact) {
filename = fullname.components(separatedBy: " ").joined(separator: "")
}
}
let fileURL = directoryURL
.appendingPathComponent(filename)
.appendingPathExtension("vcf")
let data = try CNContactVCardSerialization.data(with: contacts)
print("filename: \(filename)")
print("contact: \(String(describing: String(data: data, encoding: String.Encoding.utf8)))")
try data.write(to: fileURL, options: [.atomicWrite])
let activityViewController = UIActivityViewController(
activityItems: [fileURL],
applicationActivities: nil
)
present(activityController, animated: true, completion: nil)
}
func createContact() -> CNContact {
// Creating a mutable object to add to the contact
let contact = CNMutableContact()
contact.imageData = NSData() as Data // The profile picture as a NSData object
contact.givenName = "John"
contact.familyName = "Appleseed"
let homeEmail = CNLabeledValue(label:CNLabelHome, value:"john#example.com")
let workEmail = CNLabeledValue(label:CNLabelWork, value:"j.appleseed#icloud.com")
contact.emailAddresses = [homeEmail, workEmail]
contact.phoneNumbers = [CNLabeledValue(
label:CNLabelPhoneNumberiPhone,
value:CNPhoneNumber(stringValue:"(408) 555-0126"))]
return contact
}
Successful approach:
First get all Contacts then save it and after this make .vcf file and also share the .vcf in Emails, WhatsApp, Messaging, Skype and save in iPhone files....
#IBAction func vcfPressed(_ sender: UIButton) {
let arrayContacts = self.fetchAllContacts()
self.saveContactsInDocument(contacts: arrayContacts)
let contact = fetchAllContacts()
do {
try shareContacts(contacts: contact)
}
catch {
}
}
func shareContacts(contacts: [CNContact]) throws {
guard let directoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return}
var filename = NSUUID().uuidString
if let contact = contacts.first, contacts.count == 1 {
if let fullname = CNContactFormatter().string(from: contact) {
filename = fullname.components(separatedBy: " ").joined(separator: "")}}
let fileURL = directoryURL.appendingPathComponent(filename).appendingPathExtension("vcf")
let data = try CNContactVCardSerialization.data(with: contacts)
print("filename: \(filename)")
print("contact: \(String(data: data, encoding: String.Encoding.utf8))")
try data.write(to: fileURL, options: [.atomicWrite])
let activityViewController = UIActivityViewController(activityItems: [fileURL],applicationActivities: nil)
present(activityViewController, animated: true, completion: {})
}
func fetchAllContacts() -> [CNContact] {
var contacts : [CNContact] = []
let contactStore = CNContactStore()
let fetchReq = CNContactFetchRequest.init(keysToFetch: [CNContactVCardSerialization.descriptorForRequiredKeys()])
do {
try contactStore.enumerateContacts(with: fetchReq) { (contact, end) in
contacts.append(contact)
}}
catch {print("Failed to fetch")}
return contacts
}

How do I share files using share sheet in iOS?

I want to share some files I have locally in my app using Share Sheet functionality on iPhone. I display the file in a UIWebView and when the user clicks the share sheet, I want to show options (email, WhatsApp, etc. ) to share the file displayed on the UIWebView. I know that we can use
func displayShareSheet(shareContent:String) {
let activityViewController = UIActivityViewController(activityItems: [shareContent as NSString], applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: {})
}
to share a string for example. How do I change this code to share documents?
Swift 4.2 and Swift 5
If you already have a file in a directory and want to share it, just add it's URL into activityItems:
let fileURL = NSURL(fileURLWithPath: "The path where the file you want to share is located")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the file to the Array
filesToShare.append(fileURL)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
If you need to make the file:
I'm using this extension to make files from Data (read the comments in the code for explanation how it works):
As in the typedef's answer, get the current documents directory:
/// Get the current directory
///
/// - Returns: the Current directory in NSURL
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory as NSString
}
Extension for Data:
extension Data {
/// Data into file
///
/// - Parameters:
/// - fileName: the Name of the file you want to write
/// - Returns: Returns the URL where the new file is located in NSURL
func dataToFile(fileName: String) -> NSURL? {
// Make a constant from the data
let data = self
// Make the file path (with the filename) where the file will be loacated after it is created
let filePath = getDocumentsDirectory().appendingPathComponent(fileName)
do {
// Write the file from data into the filepath (if there will be an error, the code jumps to the catch block below)
try data.write(to: URL(fileURLWithPath: filePath))
// Returns the URL where the new file is located in NSURL
return NSURL(fileURLWithPath: filePath)
} catch {
// Prints the localized description of the error from the do block
print("Error writing the file: \(error.localizedDescription)")
}
// Returns nil if there was an error in the do-catch -block
return nil
}
}
Examples how to use:
Share image-files:
// Your image
let yourImage = UIImage()
in png-file
// Convert the image into png image data
let pngImageData = yourImage.pngData()
// Write the png image into a filepath and return the filepath in NSURL
let pngImageURL = pngImageData?.dataToFile(fileName: "nameOfYourImageFile.png")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of png image to the Array
filesToShare.append(pngImageURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
in jpg-file
// Convert the image into jpeg image data. compressionQuality is the quality-compression ratio in % (from 0.0 (0%) to 1.0 (100%)); 1 is the best quality but have bigger filesize
let jpgImageData = yourImage.jpegData(compressionQuality: 1.0)
// Write the jpg image into a filepath and return the filepath in NSURL
let jpgImageURL = jpgImageData?.dataToFile(fileName: "nameOfYourImageFile.jpg")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of jpg image to the Array
filesToShare.append(jpgImageURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
Share text-files:
// Your String including the text you want share in a file
let text = "yourText"
// Convert the String into Data
let textData = text.data(using: .utf8)
// Write the text into a filepath and return the filepath in NSURL
// Specify the file type you want the file be by changing the end of the filename (.txt, .json, .pdf...)
let textURL = textData?.dataToFile(fileName: "nameOfYourFile.txt")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the text file to the Array
filesToShare.append(textURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
Other files:
You can make a file from anything which is in Data format and as far as I know, almost everything in Swift can be converted into Data like String, Int, Double, Any...:
// the Data you want to share as a file
let data = Data()
// Write the data into a filepath and return the filepath in NSURL
// Change the file-extension to specify the filetype (.txt, .json, .pdf, .png, .jpg, .tiff...)
let fileURL = data.dataToFile(fileName: "nameOfYourFile.extension")
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the file to the Array
filesToShare.append(fileURL!)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
self.present(activityViewController, animated: true, completion: nil)
I want to share my solution of UIActivityViewController and sharing text as a image file. This solution works for sharing via Mail and even Save to Dropbox.
#IBAction func shareCsv(sender: AnyObject) {
//Your CSV text
let str = self.descriptionText.text!
filename = getDocumentsDirectory().stringByAppendingPathComponent("file.png")
do {
try str.writeToFile(filename!, atomically: true, encoding: NSUTF8StringEncoding)
let fileURL = NSURL(fileURLWithPath: filename!)
let objectsToShare = [fileURL]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
} catch {
print("cannot write file")
// failed to write file – bad permissions, bad filename, missing permissions, or more likely it can't be converted to the encoding
}
}
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
Here's the Swift 3 version:
let dictToSave: [String: Any] = [
"someKey": "someValue"
]
let jsonData = try JSONSerialization.data(withJSONObject: dictToSave, options: .prettyPrinted)
let filename = "\(self.getDocumentsDirectory())/filename.extension"
let fileURL = URL(fileURLWithPath: filename)
try jsonData.write(to: fileURL, options: .atomic)
let vc = UIActivityViewController(activityItems: [fileURL], applicationActivities: [])
self.present(vc, animated: true)
func getDocumentsDirectory() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}

How do i exactly export a csv file from iOS written in swift?

I am trying to export an cvs file.
With the following code i manage to get the file
let fileName = "sample.csv"//"sample.txt"
#IBAction func createFile(sender: AnyObject) {
let path = tmpDir.stringByAppendingPathComponent(fileName)
let contentsOfFile = "No,President Name,Wikipedia URL,Took office,Left office,Party,Home State\n1,George Washington,http://en.wikipedia.org/wiki/George_Washington,30/04/1789,4/03/1797,Independent,Virginia\n2,John Adams,http://en.wikipedia.org/wiki/John_Adams,4/03/1797,4/03/1801,Federalist,Massachusetts\n3,Thomas Jefferson,http://en.wikipedia.org/wiki/Thomas_Jefferson,4/03/1801,4/03/1809,Democratic-Republican,Virginia\n4,James Madison,http://en.wikipedia.org/wiki/James_Madison,4/03/1809,4/03/1817,Democratic-Republican,Virginia\n5,James Monroe,http://en.wikipedia.org/wiki/James_Monroe,4/03/1817,4/03/1825,Democratic-Republican,Virginia\n6,John Quincy Adams,http://en.wikipedia.org/wiki/John_Quincy_Adams,4/03/1825,4/03/1829,Democratic-Republican/National Republican,Massachusetts"
//"Sample Text repacement for future cvs data"content to save
// Write File
do {
try contentsOfFile.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
print("File sample.txt created at tmp directory")
} catch {
print("Failed to create file")
print("\(error)")
}
}
// Share button
#IBAction func shareDoc(sender: AnyObject) {
print("test share file")
docController.UTI = "public.comma-separated-values-text"
docController.delegate = self//delegate
docController.name = "Export Data"
docController.presentOptionsMenuFromBarButtonItem(sender as! UIBarButtonItem, animated: true)
//}
}
When i click the share file button in the simulator i see the following:
and with quick look it shows
So the next thing i did was testing with my iphone 5 and i tried to email sample.csv but i am only getting the message body and not the csv file???
how can i actually email the .csv file?
which export possibilities are there?
In order to email the .csv file, you can do the following:
Add this import to the top of the class. It allows you to use MFMailComposeViewController, which is a way to send emails.
import MessageUI
Generate your data, a sample I have done is:
// Creating a string.
var mailString = NSMutableString()
mailString.appendString("Column A, Column B\n")
mailString.appendString("Row 1 Column A, Row 1 Column B\n")
mailString.appendString("Row 2 Column A, Row 2 Column B\n")
// Converting it to NSData.
let data = mailString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
// Unwrapping the optional.
if let content = data {
print("NSData: \(content)")
}
Generate the MFMailComposeViewController
// Generating the email controller.
func configuredMailComposeViewController() -> MFMailComposeViewController {
let emailController = MFMailComposeViewController()
emailController.mailComposeDelegate = self
emailController.setSubject("CSV File")
emailController.setMessageBody("", isHTML: false)
// Attaching the .CSV file to the email.
emailController.addAttachmentData(data!, mimeType: "text/csv", fileName: "Sample.csv")
return emailController
}
// If the view controller can send the email.
// This will show an email-style popup that allows you to enter
// Who to send the email to, the subject, the cc's and the message.
// As the .CSV is already attached, you can simply add an email
// and press send.
let emailViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(emailViewController, animated: true, completion: nil)
}
In your case, as you have already created the file, you can simply attach that directly by changing the line where the CSV is attached to the mail for:
emailController.addAttachmentData(NSData(contentsOfFile: "YourFile")!, mimeType: "text/csv", fileName: "Sample.csv")
Answer based on: Attach csv to email xcode ,
Create CSV file in Swift and write to file
Creating CSV file in Swift
class ViewController: UIViewController {
var taskArr = [Task]()
var task: Task!
override func viewDidLoad() {
super.viewDidLoad()
task = Task()
for _ in 0..<5 {
task.name = "Raj"
task.date = "\(Date())"
task.startTime = "Start \(Date())"
task.endTime = "End \(Date())"
taskArr.append(task!)
}
creatCSV()
}
// MARK: CSV file creating
func creatCSV() -> Void {
let fileName = "Tasks.csv"
let path = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
var csvText = "Date,Task Name,Time Started,Time Ended\n"
for task in taskArr {
let newLine = "\(task.date),\(task.name),\(task.startTime),\(task.endTime)\n"
csvText.append(newLine)
}
do {
try csvText.write(to: path!, atomically: true, encoding: String.Encoding.utf8)
} catch {
print("Failed to create file")
print("\(error)")
}
print(path ?? "not found")
}
}
Task Model class
class Task: NSObject {
var date: String = ""
var name: String = ""
var startTime: String = ""
var endTime: String = ""
}
CSV output show as below format
SWIFT 5
func creatCSV() {
let fileName = "exportar_serv.csv"
/* CREAR UN ARCHIVO NUEVO EN EL DIRECTORIO PRINCIPAL */
guard let path = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(fileName) as NSURL else {
return }
var csvText = "id,name,imageName\n"
for task in taskArr {
let x : Int64 = task.id!
let id2 = String(x)
let newLine = "\(id2),\(task.name),\(task.imageName)\n"
csvText.append(newLine)
} // for
do {
try csvText.write(to: path as URL, atomically: true, encoding: String.Encoding.utf8)
print("DATOS GUARDADOS")
} catch {
print("Failed to create file")
print("\(error)")
} // catch
} // CreateCSV
Swift 5.0.1, Xcode 10.2.1 version
private func injectExportButton() {
var csvIcon: UIImage
switch self.theme {
case .dark:
csvIcon = UIImage(named: "csv-export.dark", in: Bundle.framework)!
case .light:
csvIcon = UIImage(named: "csv-export.light", in: Bundle.framework)!
}
let imgWidth = csvIcon.size.width
let imgHeight = csvIcon.size.height
let button: UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: imgWidth, height: imgHeight))
button.setBackgroundImage(csvIcon, for: UIControl.State())
button.alpha = 0
button.addTarget(self, action: #selector(csvExportButtonClicked), for: .touchUpInside)
UIView.animate(withDuration: 0.5) {
button.alpha = 1
}
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
#objc private func csvExportButtonClicked() {
debugPrint("export clicked")
createCSV()
}
private func createCSV() -> Void {
let fileName = getDocumentsDirectory().appendingPathComponent("OutputD.csv")
var csvOutputText = "Result, Date, Name\n"
history.results.forEach { result in
let newLine = "\(String(describing: result.value)),\(String(describing: result.date)),\(String(describing: result.name))\n"
csvOutputText.append(newLine)
}
do {
try csvOutputText.write(to: fileName, atomically: true, encoding: String.Encoding.utf8)
} catch {
print("Failed to create file")
print("\(error)")
}
let activity = UIActivityViewController(activityItems: ["your results", fileName], applicationActivities: nil)
present(activity, animated: true)
}
private func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}

Resources