Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- rxswift
- Git
- darkmode
- iOS16
- Archive
- SwiftUI
- Realm
- Swift
- FLUTTER
- github
- view
- mac
- JPA
- error
- Firebase
- Code
- Xcode
- 개발자
- MacOS
- IOS
- Apple
- Session
- stack
- appstore
- 한글
- Python
- UIButton
- Notification
- window
- 웹뷰
Archives
- Today
- Total
EEYatHo 앱 깎는 이야기
Swift ) xlsx 이미지까지 자유롭게 - EEYatHo iOS 본문
반응형
만약 string만 다루는 파일이라면, 그냥 csv로 하면 간단하고 가볍다.
하지만 난 이미지를 다뤄야 하는 상황이다..
image -> data -> string으로 바꾸는 헛짓거리를 하지않고,
서버에서 내려받는 image url 형식으로도 하지않고,
그냥 엑셀답게!! 셀안에 이미지를 넣는게 목적.
때문에 image를 다룰 수 있냐?를 중점으로 xlsx 라이브러리를 찾아봤다.
제공되고 있는 xlsx 관련 라이브러리들
각 라이브러리 특징
- string 읽기 불가, 쓰기 가능
- image 읽기 불가, 쓰기 가능
- 엑셀(.xlsx) 파일 생성 가능
링크 누르면 나오는 페이지에서, 중간쯤에 Installation on macOS and iOS 부분을 보면 cocoapod 설치가능
- string 읽기, 쓰기 가능
- image 읽기 가능, image 쓰기 불가 ( 지원한다고 되어있는데 작동하지 않음 ㅠ 이슈도 나와있는데 몇년째 미해결 )
- 엑셀(.xlsx) 파일 생성 불가, 꼼수를 사용하면 가능 ( 이미 있는 .xlsx파일을 열어서 수정하고 다른이름으로 저장하건 가능하기에, 빈 엑셀파일을 미리 프로젝트에 넣어두고 사용하면 기능상 불가능하진 않다 )
image 쓰기만 가능했으면, 기능상으로는 모두 상위호환이었는데 아깝다..
3. CoreXLSX
- string 읽기, 쓰기 가능
- image 자체를 지원안함 필요없어서 이 이상 안알아보았다.
Solution
엑셀파일 생성할 때는 xlsxwriter로,
읽을 때는 XlsxReaderWriter로 구현하니 잘되었다.
1. xlsxwriter 사용한 write 코드
func writeXlsx(fileName: String, maxImageLength: CGFloat = 1024.0) {
// 폴더 생성
func _makeFolder() -> String? {
let fileManager = FileManager.default
let documentUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let directoryUrl = documentUrl.appendingPathComponent("NemoXlsxFolder")
do {
try fileManager.createDirectory(atPath: directoryUrl.path, withIntermediateDirectories: true, attributes: nil)
return directoryUrl.path
}
catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
return nil
}
}
guard let foldPath = _makeFolder() else {
return
}
// 포인터들 생성
var workbook: UnsafeMutablePointer<lxw_workbook>? = nil
var sheet: UnsafeMutablePointer<lxw_worksheet>? = nil
func _makeXlsxPointer() {
let xlsxPath = "\(foldPath)/\(fileName).xlsx"
// 엑셀 파일 포인터 생성
workbook = workbook_new(xlsxPath)
// 시트 포인터 생성
sheet = workbook_add_worksheet(workbook, "Contents")
}
_makeXlsxPointer()
// 헤더(제일 윗 행) 설정
func _setXlsxHeader() {
let format = workbook_add_format(workbook)
format_set_bold(format) // 볼드 처리
// 제일 윗 줄 문자열 세팅
worksheet_write_string(sheet, 0, 0, "Animal", format)
}
_setXlsxHeader()
// 내용 채우기
func _setContents() {
let string = "cat"
let image = UIImage(named: "cat")
// 문자열 쓰기
worksheet_write_string(sheet, 1, 0, string, nil)
// 이미지 쓰기
var options = lxw_image_options()
if let image = image {
let imageScale = image.scale
let uiimageSizeInPixel = (Double(image.size.width * imageScale), Double(image.size.height * imageScale))
let bigger = uiimageSizeInPixel.0 > uiimageSizeInPixel.1 ? uiimageSizeInPixel.0 : uiimageSizeInPixel.1
var scale = 1.0
if bigger > maxImageLength {
scale = maxImageLength / bigger
}
options.x_offset = 1
options.y_offset = 1
options.x_scale = scale
options.y_scale = scale
options.object_position = 1
let buffer = getArrayOfBytesFromImage(imageData: image as NSData)
worksheet_insert_image_buffer_opt(sheet, 1, lxw_col_t(1), buffer, buffer.count, &options)
}
}
_setContents()
print("Writing Xlsx to: \(foldPath)/\(fileName)")
// 저장
workbook_close(workbook)
}
/// Update NSData to buffer for xlsxwriter
private func getArrayOfBytesFromImage(imageData: NSData) -> [UInt8] {
//Determine array size
let count = imageData.length / MemoryLayout.size(ofValue: UInt8())
//Create an array of the appropriate size
var bytes = [UInt8](repeating: 0, count: count)
//Copy image data as bytes into the array
imageData.getBytes(&bytes, length:count * MemoryLayout.size(ofValue: UInt8()))
return bytes
}
2. XlsxReaderWriter 사용한 read 코드
iPhone에서 .xlsx 파일을 선택하기 위해서는 UIDocumentPickerDelegate를 사용하면 된다
@objc func readXlsxButtonClick() {
var vc: UIDocumentPickerViewController? = nil
if #available(iOS 14.0, *) {
vc = UIDocumentPickerViewController(forOpeningContentTypes: [.compositeContent], asCopy: true)
} else {
vc = UIDocumentPickerViewController(documentTypes: ["org.openxmlformats.spreadsheetml.sheet"], in: .import)
}
if let vc = vc {
vc.delegate = self
vc.allowsMultipleSelection = false
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
}
// UIDocumentPickerDelegate
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
print(urls)
if let url = urls.first {
XlsxManager.shared.readXlsxUseXlsxReaderWriter(url: url)
}
}
// XlsxReaderWriter
func readXlsx(url: URL) {
let documentPath: String = url.path
let xlsx: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(documentPath)
if let sheet = xlsx.workbook.worksheets[0] as? BRAWorksheet {
let cellRef = "A2"
if let cell = sheet.cell(forCellReference: cellRef) {
if cell.hasError {
print("cell error: \(cell.stringValue() ?? "")")
}
if let str = cell.stringValue() {
print("cell str = \(str)")
}
if let formula = cell.formulaString() {
print("cell attr = \(formula)")
}
if let attr = cell.attributedStringValue() {
print("cell attr = \(attr)")
}
print("cell bool = \(cell.boolValue())")
print("cell int = \(cell.integerValue())")
print("cell float = \(cell.floatValue())")
if let attr = cell.attributedStringValue() {
print("cell attr = \(attr)")
}
}
if let image = sheet.image(forCellReference: cellRef)?.uiImage {
print("cell image = \(image)")
}
}
}
버그
추가로, xlsxwriter, XlsxReaderWriter 같이 설치하니까 아래 2개가 충돌이 난다.
- Pods/libxlsxwriter/zip.h 파일에서 zip_fileinfo 구조체안에 tmz_date
- Pods/XlsxReaderWriter/mz_compat.h 파일에서 zip_fileinfo 구조체안에 tmz_date
-> XlsxReaderWriter 프레임워크 안에 있는 모든 tmz_date변수들 이름을 tmz_date2로 바꿔서 해결.
-> ? 포스팅할 때 다시 tmz_date로 되돌리니까 에러가 발생하지 않음..
'iOS, Swift > Feature' 카테고리의 다른 글
Swift ) TTS (Text To Speech) - EEYatHo iOS (0) | 2022.05.05 |
---|---|
Swift ) Html to AttributedString - EEYatHo iOS (0) | 2022.04.04 |
Swift) .CSV 파일 만들기 - EEYatHo iOS (0) | 2022.02.02 |
Swift ) 디바이스 여유공간 구하기 - EEYatHo iOS (3) | 2021.07.21 |
JPA, Swift ) Apple 로그인 클라-서버 2중 인증 - EEYatHo iOS (1) | 2021.02.27 |
Comments