Latest 1.0.9
Homepage https://github.com/renebigot/XlsxReaderWriter
License MIT
Platforms ios 7.0, requires ARC
Dependencies SSZipArchive, XMLDictionary
Frameworks Foundation, UIKit

XlsxReaderWriter is an Objective-C library for iPhone / iPad and Mac. It parses and writes Excel OpenXml files (XLSX).

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
  • XMLDictionary: Converts XML to NSDictionary and NSDictionary to XML

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.dylib in Link binary with Libraries.
  • 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.

XlsxReaderWriter

Files have relationships, files are relationships… Have a look at this picture each time you want to change something in the library.

Tests coverage

A test coverage script run at the end of tests. You need to install LCOV via Macports to run coverage report generation.

Reports will be put in /Users/Shared/Coverage.

I use a custom CSS for LCOV. Put yours at this path : /Users/Shared/Coverage/gcov.css

License

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.

Latest podspec

{
    "name": "XlsxReaderWriter",
    "version": "1.0.9",
    "summary": "XlsxReaderWriter is an Objective-C library for iPhone / iPad. It parses and writes Excel OpenXml files (XLSX).",
    "homepage": "https://github.com/renebigot/XlsxReaderWriter",
    "license": "MIT",
    "authors": "Renu00e9 Bigot",
    "social_media_url": "https://twitter.com/renebigot",
    "platforms": {
        "ios": "7.0"
    },
    "source": {
        "git": "https://github.com/renebigot/XlsxReaderWriter.git",
        "tag": "1.0.9"
    },
    "source_files": "XlsxReaderWriter/*.{h,m}",
    "exclude_files": "ThirdParties",
    "frameworks": [
        "Foundation",
        "UIKit"
    ],
    "requires_arc": true,
    "dependencies": {
        "SSZipArchive": [
            "~> 0.4"
        ],
        "XMLDictionary": [
            "~> 1.4"
        ]
    }
}

Pin It on Pinterest

Share This