Skip to content

Commit 76921bc

Browse files
committed
- Code refactoring for Validation while writing(exporting) CSV file.
- Improved the code standards to handle the error status. - Split framework source files into three file. - CSVExport.swift. - CSVValidateProtocol.swift - CSVConstants.swift. - Added test code into OSX test target.
1 parent 4620b0e commit 76921bc

File tree

18 files changed

+965
-297
lines changed

18 files changed

+965
-297
lines changed

Examples/SampleSwift/SampleSwift/ViewController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class ViewController: UIViewController {
6161
// Create a object for write CSV
6262
let writeCSVObj = CSV()
6363
writeCSVObj.rows = data
64+
writeCSVObj.delimiter = DividerType.semicolon.rawValue
6465
writeCSVObj.fields = header as NSArray
6566
writeCSVObj.name = "userlist"
6667

README.md

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- Able to give CSV file name, headers and rows using property keys.
1313
- Able to convert JSON string into CSV.
1414
- Able to Read the CSV file and convert to NSDictionary.
15+
- Enable/Disable strict validation while write CSV file.
1516
- Able to Read the CSV file and convert to CSV class(Object Oriented Approach).
1617
- Support CocoaPods, mac OS and Vapor framework(Swift Package Manager).
1718
- Able to encoding CSV based on String.Encoding Type(utf8, ascii, unicode, utf16, etc) Refer: String.Encoding.
@@ -129,18 +130,31 @@ data.add(user2);
129130
// Create a object for write CSV
130131
let writeCSVObj = CSV()
131132
writeCSVObj.rows = data
133+
writeCSVObj.delimiter = DividerType.comma.rawValue
132134
writeCSVObj.fields = header as NSArray
133135
writeCSVObj.name = "userlist"
134136

135137
// Write File using CSV class object
136-
let filePath:String = SwiftCSVExport.exportCSV(writeCSVObj);
137-
print("File Path: \(filePath)")
138+
let result = exportCSV(writeCSVObj);
139+
if result.isSuccess {
140+
guard let filePath = result.value else {
141+
print("Export Error: \(String(describing: result.value))")
142+
return
143+
}
144+
self.testWithFilePath(filePath, rowCount: data.count, columnCount: header.count)
145+
print("File Path: \(filePath)")
146+
147+
// Read File and convert as CSV class object
148+
let readCSVObj = readCSVObject(filePath);
149+
150+
// Use 'SwiftLoggly' pod framework to print the Dictionary
151+
loggly(LogType.Info, text: readCSVObj.name)
152+
} else {
153+
print("Export Error: \(String(describing: result.value))")
154+
}
155+
156+
138157

139-
// Read File and convert as CSV class object
140-
let readCSVObj = readCSVObject(filePath);
141-
142-
// Use 'SwiftLoggly' pod framework to print the Dictionary
143-
loggly(LogType.Info, text: readCSVObj.name)
144158

145159
```
146160

@@ -161,14 +175,29 @@ userid,name,email,message,isValidUser,balance
161175

162176
```
163177

164-
### Example 3 - Swift
178+
### Example 3 - Swift - Enable Strict Validation
165179

166180
```swift
167181

182+
// Enable Strict Validation
183+
CSVExport.export.enableStrictValidation = true
184+
168185
// Able to convert JSON string into CSV.
169186
let string = "[{\"name\":\"vignesh\",\"email\":\"[email protected]\"},{\"name\":\"vinoth\",\"email\":\"[email protected]\"}]";
170-
let filePath:String = exportCSV("userlist", fields:["name","email"], values:string);
171-
print(filePath)
187+
188+
// Write File using CSV class object
189+
let result1 = exportCSV("userlist", fields:["userid","name","email"], values:string);
190+
XCTAssertEqual(false, result1.isSuccess)
191+
if result1.isSuccess {
192+
guard let filePath = result1.value else {
193+
print("Export Error: \(String(describing: result1.value))")
194+
return
195+
}
196+
print("File Path: \(filePath)")
197+
198+
} else {
199+
print("Export Error: \(String(describing: result1.value))")
200+
}
172201

173202

174203
```
@@ -177,7 +206,7 @@ print(filePath)
177206

178207
```swift
179208

180-
File Path: xxxxxx/xxxxxxx/Documents/Exports/userlist.csv
209+
Export Error: Optional("Expected 3 columns, But Parsed 2 columns on row 1")
181210

182211
```
183212

@@ -259,6 +288,10 @@ CSVExport.export.fileName = "Sample" //default is "csvfile"
259288
//Set the directory in which the csv files will be written
260289
CSVExport.export.directory = "/Library/XXX-folder-name-XXX" //default is the standard exporting directory for each platform.
261290

291+
// Able to set strict validation while create a new CSV file.
292+
CSVExport.export.enableStrictValidation = true
293+
294+
262295
```
263296

264297
## Installation

Sources/CSVConstants.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//
2+
// CSVConstants.swift
3+
// SwiftCSVExport
4+
//
5+
// Created by Vignesh on 12/01/18.
6+
// Copyright © 2018 vigneshuvi. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
//MARK: - CSV output dictionay keys - Constants
12+
public struct FieldName {
13+
public static let fields = "fields"
14+
public static let rows = "rows"
15+
public static let name = "name"
16+
public static let divider = "divider"
17+
}
18+
19+
//MARK: - Divider type - Enumeration
20+
public enum DividerType: String {
21+
case comma = ","
22+
case semicolon = ";"
23+
}
24+
25+
// MARK: - CSV Class
26+
@objc public class CSV:NSObject {
27+
open var fields:NSArray = []
28+
open var rows:NSArray = []
29+
open var name:String = ""
30+
open var delimiter:String = DividerType.comma.rawValue
31+
}
32+
33+
// MARK: - Extension for NSMutableDictionary
34+
public extension NSMutableDictionary {
35+
36+
public var hasData:Bool {
37+
return self.allKeys.count > 0 && self.allValues.count > 0
38+
}
39+
40+
public var fields: [Any] {
41+
guard let fields = self.object(forKey:FieldName.fields) else {
42+
return []
43+
}
44+
return fields as! [Any];
45+
}
46+
47+
public var rows: [Any] {
48+
guard let rows = self.object(forKey:FieldName.rows) else {
49+
return []
50+
}
51+
return rows as! [Any]
52+
}
53+
54+
public var name: String {
55+
guard let name = self.object(forKey:FieldName.name) else {
56+
return ""
57+
}
58+
return name as! String
59+
}
60+
61+
public var delimiter: String {
62+
guard let delimiter = self.object(forKey:FieldName.divider) else {
63+
return ""
64+
}
65+
return delimiter as! String
66+
}
67+
}
68+
69+
// MARK: - Extension for String
70+
extension String {
71+
72+
/// Get lines split by Newline delimiter.
73+
var lines: [String] {
74+
var result: [String] = []
75+
enumerateLines { line, _ in result.append(line) }
76+
return result
77+
}
78+
79+
func split(regex pattern: String) -> [String] {
80+
81+
guard let re = try? NSRegularExpression(pattern: pattern, options: [])
82+
else { return [] }
83+
84+
let nsString = self as NSString // needed for range compatibility
85+
let stop = "<SomeStringThatYouDoNotExpectToOccurInSelf>"
86+
let modifiedString = re.stringByReplacingMatches(
87+
in: self,
88+
options: [],
89+
range: NSRange(location: 0, length: nsString.length),
90+
withTemplate: stop)
91+
return modifiedString.components(separatedBy: stop)
92+
}
93+
94+
/// Getting the characters length
95+
var length: Int {
96+
return self.count
97+
}
98+
99+
/// Replace the escape characters
100+
func replaceEscapeCharacters() -> String {
101+
return self.replacingOccurrences(of: "\n", with: "\\n").replacingOccurrences(of: "\t", with: "\\t").replacingOccurrences(of: "\r", with: "\\r")
102+
}
103+
104+
/// Create CSV Row
105+
func formatCSVRow(_ div:String, value:Any) -> String {
106+
if let string = value as? String {
107+
// Wrap around double quotes
108+
let fString = "\"\(string)\""
109+
return self.length == 0 ? fString : "\(self)\(div) \(fString)"
110+
} else {
111+
return self.length == 0 ? "\(value)" : "\(self)\(div) \(value)"
112+
}
113+
}
114+
115+
func stringByAppendingPathComponent(path: String) -> String {
116+
let nsSt = self as NSString
117+
return nsSt.appendingPathComponent(path)
118+
}
119+
}

0 commit comments

Comments
 (0)