Skip to content

Commit e059d50

Browse files
Update README.md
1 parent aa51d5a commit e059d50

1 file changed

Lines changed: 174 additions & 76 deletions

File tree

README.md

Lines changed: 174 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,174 @@
1-
This is a Kotlin Multiplatform project targeting Android, iOS, Web, Desktop (JVM).
2-
3-
* [/composeApp](./composeApp/src) is for code that will be shared across your Compose Multiplatform applications.
4-
It contains several subfolders:
5-
- [commonMain](./composeApp/src/commonMain/kotlin) is for code that’s common for all targets.
6-
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name.
7-
For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app,
8-
the [iosMain](./composeApp/src/iosMain/kotlin) folder would be the right place for such calls.
9-
Similarly, if you want to edit the Desktop (JVM) specific part, the [jvmMain](./composeApp/src/jvmMain/kotlin)
10-
folder is the appropriate location.
11-
12-
* [/iosApp](./iosApp/iosApp) contains iOS applications. Even if you’re sharing your UI with Compose Multiplatform,
13-
you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
14-
15-
### Build and Run Android Application
16-
17-
To build and run the development version of the Android app, use the run configuration from the run widget
18-
in your IDE’s toolbar or build it directly from the terminal:
19-
- on macOS/Linux
20-
```shell
21-
./gradlew :composeApp:assembleDebug
22-
```
23-
- on Windows
24-
```shell
25-
.\gradlew.bat :composeApp:assembleDebug
26-
```
27-
28-
### Build and Run Desktop (JVM) Application
29-
30-
To build and run the development version of the desktop app, use the run configuration from the run widget
31-
in your IDE’s toolbar or run it directly from the terminal:
32-
- on macOS/Linux
33-
```shell
34-
./gradlew :composeApp:run
35-
```
36-
- on Windows
37-
```shell
38-
.\gradlew.bat :composeApp:run
39-
```
40-
41-
### Build and Run Web Application
42-
43-
To build and run the development version of the web app, use the run configuration from the run widget
44-
in your IDE's toolbar or run it directly from the terminal:
45-
- for the Wasm target (faster, modern browsers):
46-
- on macOS/Linux
47-
```shell
48-
./gradlew :composeApp:wasmJsBrowserDevelopmentRun
49-
```
50-
- on Windows
51-
```shell
52-
.\gradlew.bat :composeApp:wasmJsBrowserDevelopmentRun
53-
```
54-
- for the JS target (slower, supports older browsers):
55-
- on macOS/Linux
56-
```shell
57-
./gradlew :composeApp:jsBrowserDevelopmentRun
58-
```
59-
- on Windows
60-
```shell
61-
.\gradlew.bat :composeApp:jsBrowserDevelopmentRun
62-
```
63-
64-
### Build and Run iOS Application
65-
66-
To build and run the development version of the iOS app, use the run configuration from the run widget
67-
in your IDE’s toolbar or open the [/iosApp](./iosApp) directory in Xcode and run it from there.
68-
69-
---
70-
71-
Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html),
72-
[Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform/#compose-multiplatform),
73-
[Kotlin/Wasm](https://kotl.in/wasm/)…
74-
75-
We would appreciate your feedback on Compose/Web and Kotlin/Wasm in the public Slack channel [#compose-web](https://slack-chats.kotlinlang.org/c/compose-web).
76-
If you face any issues, please report them on [YouTrack](https://youtrack.jetbrains.com/newIssue?project=CMP).
1+
# FileMapper KMP
2+
3+
![Kotlin](https://img.shields.io/badge/kotlin-multiplatform-blue.svg?logo=kotlin)
4+
![Compose](https://img.shields.io/badge/Compose-Multiplatform-green.svg)
5+
![Android](https://img.shields.io/badge/Android-3DDC84.svg?logo=android&logoColor=white)
6+
![iOS](https://img.shields.io/badge/iOS-000000.svg?logo=apple&logoColor=white)
7+
![Desktop](https://img.shields.io/badge/Desktop-4A4A55.svg)
8+
![Web](https://img.shields.io/badge/Web-654FF0.svg?logo=webassembly&logoColor=white)
9+
![License](https://img.shields.io/badge/license-MIT-blue.svg)
10+
![Version](https://img.shields.io/badge/version-1.0.0-orange.svg)
11+
12+
A lightweight, powerful **Kotlin Multiplatform (KMP)** library designed to seamlessly map files (XLSX, JSON) to Kotlin Data Classes. Supporting Android, iOS, Desktop, and Web (Wasm/JS), it provides both Compose-ready UI triggers and pure logic-based APIs.
13+
14+
-----
15+
16+
## 🚀 Features
17+
18+
| Feature | Description |
19+
| :--- | :--- |
20+
| **Multi-Format** | Support for `.xlsx` and `.json` file types. |
21+
| **Type-Safe Mapping** | Automatically converts file rows/objects into Kotlin Data Classes. |
22+
| **Platform-Agnostic** | Unified API for Android, iOS, Desktop (JVM), and Web (Wasm/JS). |
23+
| **Compose Integration** | Pre-built Composable controller for easy state management. |
24+
| **Flexible Logic** | Pure `suspend` functions for Use Cases and ViewModels. |
25+
| **Excel Control** | Use annotations to map specific columns or ignore unmapped data. |
26+
27+
-----
28+
29+
## 📦 Setup
30+
31+
Add the dependency to your `commonMain` source set in `build.gradle.kts`:
32+
33+
```kotlin
34+
kotlin {
35+
sourceSets {
36+
commonMain.dependencies {
37+
implementation("io.github.mamon-aburawi:filemapper-kmp:{last_version}")
38+
}
39+
}
40+
}
41+
```
42+
43+
-----
44+
45+
## 🛠 Implementation
46+
47+
### 1\. Define your Data Model
48+
49+
Ensure your data class is annotated with `@Serializable` (from `kotlinx.serialization`) and use `@ColumnName` to link Excel headers.
50+
51+
```kotlin
52+
import kotlinx.serialization.Serializable
53+
import io.mamon.filemapper.ColumnName
54+
55+
@Serializable
56+
data class Employee(
57+
@ColumnName("Full Name") // Matches Excel Header
58+
val name: String,
59+
60+
@ColumnName("Email Address")
61+
val email: String,
62+
63+
val age: Int
64+
)
65+
```
66+
67+
### 2\. Usage in Compose (UI)
68+
69+
Use the `rememberFileMapper` controller for a seamless UI experience. It handles picking, importing, and exporting in one place.
70+
71+
```kotlin
72+
val fileMapperController = rememberFileMapper<Employee>(
73+
fileType = selectedFileType,
74+
onImportSuccess = { employeeList ->
75+
mEmployees = employeeList
76+
statusMessage = "Successfully imported ${employeeList.size} employees."
77+
},
78+
onExportSuccess = { savedPath ->
79+
statusMessage = "Successfully exported to $savedPath"
80+
},
81+
onImportFailed = { error ->
82+
statusMessage = error.getLocalizedMessage()
83+
},
84+
onExportFailed = { error ->
85+
statusMessage = "Export Error: ${error.getLocalizedMessage()}"
86+
}
87+
)
88+
89+
// Trigger the picker
90+
Button(onClick = { fileMapperController.import() }) {
91+
Text("Import Employees")
92+
}
93+
94+
// Trigger the export
95+
Button(onClick = { fileMapperController.export(mEmployees, "YourFileName") }) {
96+
Text("Export to Excel")
97+
}
98+
```
99+
100+
### 3\. Usage in Non-Compose (Logic)
101+
102+
Trigger picking and mapping from a ViewModel or shared logic using the `FileMapperPicker` and `importData` API.
103+
104+
```kotlin
105+
scope.launch {
106+
// 1. Pick the file using the platform picker
107+
val file = FileMapperPicker.pickFile(type = selectedFileType)
108+
109+
if (file != null) {
110+
// 2. Read bytes and import data
111+
fileMapper.importData<Employee>(
112+
bytes = file.readBytes(),
113+
ignoreColumns = emptySet(),
114+
onSuccess = { employeeList ->
115+
mEmployees = employeeList
116+
statusMessage = "Successfully imported ${employeeList.size} employees."
117+
},
118+
onFailed = { error ->
119+
statusMessage = error.getLocalizedMessage()
120+
}
121+
)
122+
}
123+
}
124+
```
125+
126+
-----
127+
128+
## 📑 Annotations & Configuration
129+
130+
| Annotation / Property | Description |
131+
| :--- | :--- |
132+
| `@Serializable` | Required for the engine to parse the data class structure. |
133+
| `@ColumnName("Name")` | Maps a specific Excel header string to a Kotlin property. |
134+
| `ignoreUnmappedColumns` | used if you want to ignore the columns in the excel file that does not mapped in data class. |
135+
| `ignoreColumns` | Set of strings to skip during the export/import process. |
136+
137+
-----
138+
139+
## ⚠️ Errors & Exceptions
140+
141+
The library uses a specialized `FileMapperException` to provide localized feedback.
142+
143+
| Error Code | Meaning |
144+
| :--- | :--- |
145+
| `EMPTY_FILE` | The selected file is empty. |
146+
| `INVALID_FORMAT` | Invalid file format. Expected XLSX or JSON. |
147+
| `READ_FAILED` | Failed to read the selected file. |
148+
| `EXPORT_FAILED` | An error occurred during export. |
149+
| `NO_DATA_ROWS` | The file contains no data rows. |
150+
| `ALL_COLUMNS_IGNORED` | All columns for the target data class are ignored. |
151+
| `MISSING_COLUMNS` | Missing Required Columns. |
152+
| `UNEXPECTED_COLUMNS` | Unexpected Columns found. |
153+
| `UNEXPECTED_ERROR` | An unexpected error occurred. |
154+
155+
### Localized Messages
156+
157+
Retrieve error messages in the user's system language (English/Arabic) automatically:
158+
159+
```kotlin
160+
// Works in both Compose and Non-Compose (Suspend) contexts
161+
val message = exception.getLocalizedMessage()
162+
```
163+
164+
-----
165+
166+
## 🌟 Support the Project
167+
168+
If this library helped you save time on your KMP project, please consider giving it a star\! It helps more developers find the project.
169+
170+
**[ ⭐ Star this Repository ]**
171+
172+
-----
173+
174+
*Developed by [Mamon Aburawi](https://github.com/mamon-aburawi) — 2026*

0 commit comments

Comments
 (0)