XlsxReaderWriter
XlsxReaderWriter is an Objective-C library for iPhone / iPad and Mac. It parses and writes Excel OpenXml files (XLSX).
Swift Package Manager
Integrate usingAdd the SPM Dependency to your project:
https://github.com/charlymr/XlsxReaderWriter
WARNING: Use from version 2.4.3
Add the Library to your target.
Select the Project file -> General -> Framewors, Libraries, and Embededded Content => Add -> XlsxReaderWriter
Add the import to your source
Swift
import XlsxReaderWriter
Integrate using Carthage
Install Carthage if not already available
Change to the directory of your Xcode project, and Create and Edit your CartFile and add XlsxReaderWriter: Using Carthage with Xcode 12
$ cd /path/to/MyProject
$ touch CartFile
$ edit CartFile
github "charlymr/XlsxReaderWriter" ~> 2.4.3
Save and run:
$ carthage update --use-xcframeworks
Drop the Carthage/Build/iOS .framework in your project.
For more details on Cartage and how to use it, check the Carthage Github documentation
COCOAPODS is OUTDATED - IMPORTANT READ THIS:
Cocoapods is outdated v 1.0.11, and apprently it is not possible to update it anymore: https://cocoapods.org/pods/XlsxReaderWriter if you want to fix it and use the latest version
Install Cocoapods (gem)
Either install cocoapods with the official documentation https://cocoapods.org or with gem
source bundle.sh
Frome here, instead of pod install
use lbundle exec pod install
Update you Podfile
Method 1 The quick one:
Just change your pod to this. Please not the branch (here 2.4.3) It will change in the future and be merge in master, so keep checkign for update.
## Change in your Podfile.
pod 'XlsxReaderWriter', podspec: 'https://raw.githubusercontent.com/charlymr/XlsxReaderWriter/2.4.3/XlsxReaderWriter.podspec'
Method 2 (Stay up to date automatically):
## Change in your Podfile.
pod 'XlsxReaderWriter', '~> 2.4', :source => 'https://github.com/charlymr/XlsxReaderWriter-Podspecs.git'
(optional) If you want faster Build you can add the source
## Add this to your PodFile (at the top)
source 'https://github.com/charlymr/XlsxReaderWriter-Podspecs.git'
## Then you can get the latest version 2.4 +
pod 'XlsxReaderWriter', '~> 2.4'
Features
XlsxReaderWriter is able to:
- Read a spreadsheet document (XLSX file)
- Save a spreadsheet document
- Create worksheet
- Copy worksheet
- Remove worksheet
- Read cells content (Formula, error, string, attributed string, formatted number, boolean, date)
- Write cells content (Formula, error, string, attributed string, formatted number, boolean, date)
- Get images
- Add images (JPEG or PNG)
- Add/remove rows in sheets
- Add/remove columns in sheets
- Change number formatting
- Read content from merge cells
- Get cell fill as a UIColor
- Change cell fill
- ... many other things
TODO:
- Add/remove columns in sheets
- Create spreadsheet document from scratch
- Improve number formatting
- Borders
- Add better support for comments (add, remove, read)
Limitation
XlsxReaderWriter can't create a SpreadsheetML (XLSX) file from scratch. You have to open an existing file and modify it before saving it. Not really a problem: Create your file with Excel or Numbers with all the needed formatting (fills, borders, etc.) then include the file as a resource of your project.
Third parties
Third parties are included in this repository, not linked as git submodules.
- SSZipArchive: Compression/decompression library
Third parties (Modified)
- XMLDictionary: Converts XML to NSDictionary and NSDictionary to XML The Library is Deprecated, for this reason the code has been integrated and refactored to avoid Name collision
Linking (Objective-C)
To include the library to your Xcode project:
- Create a new project or open an existing project
- Insert XlsxReaderWriter.xcodeproj as a sub project of your project
- In your target Build phases insert XlsxReaderWriter as a target dependency
- Add libXlsxReaderWriter.a and libz.tbd in Link binary with Libraries. Older systems can use libz.dylib instead of libz.tbd.
- Add -all_load in Linking / Other Linker Flags in your project settings
- Add the XlsxReaderWriter root directory path to User Header Search Paths and set it as recursive. For example, set the path to "$(SRCROOT)/XlsxReaderWriter/", not "$(SRCROOT)/XlsxReaderWriter/XlsxReaderWriter/".
Now, you can import BRAOfficeDocumentPackage.h in your code.
Linking (Swift bridging)
If you want to use this library from some Swift code, be sure to follow the same steps as in the Objective-C linking, then:
- you should #import "XlsxReaderWriter-swift-bridge.h" in your bridge header file
- if you don't have any bridge header file, create a new .h file, and #import "XlsxReaderWriter-swift-bridge.h"
- Set the path to your bridge file in your project settings : Swift Compiler - Code Generation / Objective-C Bridging Header.
More info about this could be find here
How to
Read a spreadsheet document (XLSX file)
Objective-C
NSString *documentPath = [[NSBundle mainBundle] pathForResource:@"testWorkbook" ofType:@"xlsx"];
BRAOfficeDocumentPackage *spreadsheet = [BRAOfficeDocumentPackage open:documentPath];
Swift
var documentPath: String = NSBundle.mainBundle().pathForResource("testWorkbook", ofType: "xlsx")
var spreadsheet: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(documentPath)
Save a spreadsheet document
Objective-C
//Save
[spreadsheet save];
//Save a copy
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"workbookCopy.xlsx"];
[spreadsheet saveAs:fullPath];
Swift
//Save
spreadsheet.save()
//Save a copy
var fullPath: String = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true).lastObject().stringByAppendingPathComponent("workbookCopy.xlsx")
spreadsheet.saveAs(fullPath)
Get a worksheet
Objective-C
//First worksheet in the workbook
BRAWorksheet *firstWorksheet = spreadsheet.workbook.worksheets[0];
//Worksheet named "Foo"
BRAWorksheet *fooWorksheet = [spreadsheet.workbook createWorksheetNamed:@"Foo"];
Swift
//First worksheet in the workbook
var firstWorksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0]
//Worksheet named "Foo"
var fooWorksheet: BRAWorksheet = spreadsheet.workbook.createWorksheetNamed("Foo")
Read cells content: Formula
Objective-C
NSString *formula = [[worksheet cellForCellReference:@"B4"] formulaString]
Swift
var formula: String = worksheet.cellForCellReference("B4").formulaString()
Read cells content: error
Objective-C
NSString *errorValue = nil;
if ([[worksheet cellForCellReference:@"B2"] hasError]) {
errorValue = [[worksheet cellForCellReference:@"B2"] stringValue];
}
Swift
var errorValue: String? = nil
if worksheet.cellForCellReference("B2").hasError() {
errorValue = worksheet.cellForCellReference("B2").stringValue()
}
Read cells content: string
Objective-C
NSString *string = [[worksheet cellForCellReference:@"B6"] stringValue];
Swift
var string: String = worksheet.cellForCellReference("B6").stringValue()
Read cells content: attributed string
Objective-C
//Cell style is applied to the cell content
NSAttributedString *attributedString = [[worksheet cellForCellReference:@"B5"] attributedStringValue];
Swift
//Cell style is applied to the cell content
var attributedString: NSAttributedString = worksheet.cellForCellReference("B5").attributedStringValue()
Read cells content: formatted number
Objective-C
//Integer cell value
NSInteger cellIntValue = [[worksheet cellForCellReference:@"B5"] integerValue];
//Float cell value
CGFloat cellFloatValue = [[worksheet cellForCellReference:@"B5"] floatValue];
//Formatted number cell value
CGFloat cellFloatValue = [[worksheet cellForCellReference:@"B5"] stringValue];
Swift
//Integer cell value
var cellIntValue: Int = CInteger(worksheet.cellForCellReference("B5"))!
//Float cell value
var cellFloatValue: CGFloat = CFloat(worksheet.cellForCellReference("B5"))!
//Formatted number cell value
var cellFloatValue: CGFloat = worksheet.cellForCellReference("B5").stringValue()
Read cells content: boolean
Objective-C
BOOL cellTruth = [[worksheet cellForCellReference:@"B5"] boolValue];
Swift
var cellTruth: Bool = CBool(worksheet.cellForCellReference("B5"))!
Write cells content: Formula
Objective-C
[[worksheet cellForCellReference:@"Y26" shouldCreate:YES] setFormulaString:@"TODAY()"];
Swift
worksheet.cellForCellReference("Y26", shouldCreate: true).formulaString = "TODAY()"
Write cells content: error
Objective-C
[[worksheet cellForCellReference:@"Y27" shouldCreate:YES] setError:@"#DIV/0!"];
Swift
worksheet.cellForCellReference("Y27", shouldCreate: true).error = "#DIV/0!"
Write cells content: string
Objective-C
[[worksheet cellForCellReference:@"Y24" shouldCreate:YES] setStringValue:@"FOO / BAR"];
Swift
worksheet.cellForCellReference("Y24", shouldCreate: true).stringValue = "FOO / BAR"
Write cells content: attributed string
Objective-C
[[worksheet cellForCellReference:@"Z24" shouldCreate:YES]
setAttributedStringValue:[[NSAttributedString alloc] initWithString:@"RED is not GREEN" attributes:@{NSForegroundColorAttributeName: [UIColor greenColor]}]];
Swift
worksheet.cellForCellReference("Z24", shouldCreate: true).attributedStringValue = NSAttributedString(string: "RED is not GREEN", attributes: [NSForegroundColorAttributeName: UIColor.greenColor()])
Write cells content: formatted number
Objective-C
[[worksheet cellForCellReference:@"Z23" shouldCreate:YES] setFloatValue:12.3];
[[worksheet cellForCellReference:@"Z23"] setNumberFormat:@"0.000"];
Swift
worksheet.cellForCellReference("Z23", shouldCreate: true).floatValue = 12.3
worksheet.cellForCellReference("Z23").numberFormat = "0.000"
Write cells content: boolean
Objective-C
[[worksheet cellForCellReference:@"Z21" shouldCreate:YES] setBoolValue:NO];
Swift
worksheet.cellForCellReference("Z21", shouldCreate: true).boolValue = false
Write cells content: date
Objective-C
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateFormat = @"MM/dd/yyyy";
[[worksheet cellForCellReference:@"Y25" shouldCreate:YES] setDateValue:[df dateFromString:@"10/07/1982"]];
[[worksheet cellForCellReference:@"Y25"] setNumberFormat:@"m/d/yyyy"];
Swift
var df: NSDateFormatter = NSDateFormatter()
df.dateFormat = "MM/dd/yyyy"
worksheet.cellForCellReference("Y25", shouldCreate: true).dateValue = df.dateFromString("10/07/1982")
worksheet.cellForCellReference("Y25").numberFormat = "m/d/yyyy"
Get cell fill as a UIColor
Objective-C
UIColor *cellFillColor = [[worksheet cellForCellReference:@"A35"] cellFillColor];
Swift
var cellFillColor: UIColor = worksheet.cellForCellReference("A35").cellFillColor()
Change cell fill
Objective-C
[[worksheet cellForCellReference:@"A36" shouldCreate:YES] setCellFillWithForegroundColor:[UIColor yellowColor] backgroundColor:[UIColor blackColor] andPatternType:kBRACellFillPatternTypeDarkTrellis];
Swift
worksheet.cellForCellReference("A36", shouldCreate: true).setCellFillWithForegroundColor(UIColor.yellowColor(), backgroundColor: UIColor.blackColor(), andPatternType: kBRACellFillPatternTypeDarkTrellis)
Get images
Objective-C
//Works with oneCellAnchor or twoCellAnchored image
UIImage *image = [worksheet imageForCellReference:@"G8"].uiImage;
Swift
//Works with oneCellAnchor or twoCellAnchored image
var image: UIImage = worksheet.imageForCellReference("G8").uiImage
Add images (JPEG or PNG)
Objective-C
UIImage *image = [UIImage imageNamed:@"Kitten.jpeg"];
//preserveTransparency force JPEG (NO) or PNG (YES)
BRAWorksheetDrawing *drawing = [worksheet addImage:image betweenCellsReferenced:@"G2" and:@"I10"withInsets:UIEdgeInsetsZero preserveTransparency:NO];
//Set drawing insets (percentage)
drawing.insets = UIEdgeInsetsMake(0., 0., .5, .5);
Swift
var image: UIImage = UIImage(named: "Kitten.jpeg")
//preserveTransparency force JPEG (NO) or PNG (YES)
var drawing: BRAWorksheetDrawing = worksheet.addImage(image, betweenCellsReferenced: "G2", and: "I10", withInsets: UIEdgeInsetsZero, preserveTransparency: false)
//Set drawing insets (percentage)
drawing.insets = UIEdgeInsetsMake(0.0, 0.0, 0.5, 0.5)
Add/remove rows in sheets
Objective-C
//Insert one row before 18th row
[worksheet addRowsAt:18];
//Remove it
[worksheet removeRow:18];
//Insert 10 rows before 18th row
[worksheet addRowsAt:18 count:10];
//Remove them
[worksheet removeRow:18 count:10];
Swift
//Insert one row before 18th row
worksheet.addRowsAt(18)
//Remove it
worksheet.removeRow(18)
//Insert 10 rows before 18th row
worksheet.addRowsAt(18, count: 10)
//Remove them
worksheet.removeRow(18, count: 10)
Add/remove columns in sheets
TODO
Change number formatting
Objective-C
[[worksheet cellForCellReference:@"Y25"] setNumberFormat:@"_(0.00_);(0.00)"];
Swift
worksheet.cellForCellReference("Y25").numberFormat = "_(0.00_);(0.00)"
Read content from merge cells
Objective-C
//Get the cell at C10 or the upper-left cell if C10 belongs to a merge cell
BRACell *cell = [worksheet cellOrFirstCellInMergeCellForCellReference:@"C10"]
Swift
//Get the cell at C10 or the upper-left cell if C10 belongs to a merge cell
var cell: BRACell = worksheet.cellOrFirstCellInMergeCellForCellReference("C10")
Create worksheet
Objective-C
BRAWorksheet *worksheet = [spreadsheet.workbook createWorksheetNamed:@"Foo"];
Swift
var worksheet: BRAWorksheet = spreadsheet.workbook.createWorksheetNamed("Foo")
Copy worksheet
Objective-C
BRAWorksheet *worksheetToCopy = spreadsheet.workbook.worksheets[0];
BRAWorksheet *worksheet = [spreadsheet.workbook createWorksheetNamed:@"Foo" byCopyingWorksheet:worksheetToCopy];
Swift
var worksheetToCopy: BRAWorksheet = spreadsheet.workbook.worksheets[0]
var worksheet: BRAWorksheet = spreadsheet.workbook.createWorksheetNamed("Foo", byCopyingWorksheet: worksheetToCopy)
Remove worksheet
Objective-C
[_spreadsheet.workbook removeWorksheetNamed:@"Foo"];
Swift
spreadsheet.workbook.removeWorksheetNamed("Foo")
Do some simple operation from Swift
let documentPath = NSBundle.mainBundle().pathForResource("testWorkbook", ofType: "xlsx")
let odp = BRAOfficeDocumentPackage.open(documentPath)
let worksheet: BRAWorksheet = odp!.workbook.worksheets[0] as! BRAWorksheet;
NSLog("%@", worksheet.cellForCellReference("A1").attributedStringValue())
let paths: Array = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) as Array
let fullPath: String = (paths[0] as! String).stringByAppendingString("testSaveAs.xlsx")
odp!.saveAs(fullPath)
A word about XLSX files
XLSX files are OPC packages (see ECMA-376 for more information). Below is a simplified hierarchical representation of the package contents.
Files have relationships, files are relationships... Have a look at this picture each time you want to change something in the library.
License
Copyright (c) 2017 Denis Martin-Bruillot (Trying to keep it working)
Copyright (c) 2014-2016 René BIGOT.
Copyright (c) 2015 Fabian Pahl (Cocoa pods integration).
Copyright (c) 2016 Sam Hatchett (Mac port).
The XlsxReaderWriter library should be accompanied by a LICENSE file. This file contains the license relevant to this distribution. If no license exists, please contact me @renebigot.