Sweet Brissie life

ブリスベンでのサトウキビ博士研究生活の甘くない備忘録

React Native + Expo 記録アプリ⑤ FileSystem & Sharing for csv export

 さて、このシリーズもアプリの実装紹介としては最後になります。

 

 エクスポート、こんな感じのアレです。データベースをcsvで他のメディアに投げます。

 

もtもと費やしたお金と時間を全部記録して可視化するアプリがほしい!という動機で作り始めたはいいものの、なんだかんだこのアプリのデータベースだけに記録が閉じ込められちゃうのも不安だし、思ったほど高度な可視化や分析はできなさそうだし...ということで、一応データベースをcsvにしてエクスポートしたい(逃)!ということで実装した機能の紹介です。

 

本記事のコードのjsファイルなどはこちら。

Life-Report/SettingScreen.js at master · tkd708/Life-Report · GitHub

 

 

 

FileSystem

とはいえ調べていてもcsv exportの実装例は見当たらず....出てきたのはtext fileを作ってアプリ内部に保存する、というもの。 

 
そこで出てきたこのFileSystem、これによってアプリのファイルシステムにアクセスしてファイルを書き込んだり消したりできるんですね。いろんな操作があるみたいです。

docs.expo.io

一応、こうしてインポートしておけばそれぞれの関数が実行できます。

import * as FileSystem from 'expo-file-system';

 

 

JSON to CSV

上記のStackOverFlowの例ではtextだったけれど、要はこれをカンマ区切りの記述に直してファイルの拡張子を.csvで保存してやればいいんだよね?ということで、JSON object をcsv formatにするコードは適当に拝借しました。

medium.com

    const convertToCSV = (objArray=> {
        var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
        var str = '';
        var headerLine = 'ID, Date, Type, Category, Amount, Remark';
        str += headerLine + '\r\n';

        for (var i = 0i < array.lengthi++) {
            var line = '';
            for (var index in array[i]) {
                if (line != ''line += ','

                line += array[i][index];
            }

            str += line + '\r\n';
        }

        return str;
    }

こんな感じで修正し、データベースから引っ張ってきた配列(その一つ一つがオブジェクトで、更にそのKeyがHeaderに対応する形のデータセット)をcsv形式に変更する関数を導入。

 

 

Sharing

 ただ、自分としては生成したファイルをアプリ内に保存しておくのではなく、例えば自分のPCとかに置いておけるようにDropboxなりにExportしたい...他のアプリでもできてるアレはどうやって実装されてるの?

と探し回っていたらありました、Expo Sharingなるものが。これで冒頭の画像のように他のメディアに投げるアレを出すことができるみたいです。

docs.expo.io

 インポートも同じように。

import * as Sharing from 'expo-sharing';

 

 

で、これらFileSystemとSharingをまとめてcsvエクスポート用の関数を用意してみたのがこちら。

    const exportFile = async () => {
        let fileName = "LifeReport_allExpenses_" + String(moment(new Date()).add(0'days').format('YYYY-MM-DD'));
        let fileUri = FileSystem.documentDirectory + fileName + ".csv";
        let txtFile = convertToCSV(container.state.allExpenses);
        await FileSystem.writeAsStringAsync(fileUritxtFile, { encoding: FileSystem.EncodingType.UTF8 });
        await Sharing.shareAsync(fileUri)
        await FileSystem.deleteAsync(fileUri)
    }

大体そのまま読めると思いますが、fileNameはアプリ名とデータ名に日付を足したもので、FileSystem.documentDirectoryと拡張子と組み合わせることで保存先uriになっています。

で、txtFileとなってますがこれは上記の関数でデータベースをcsv化したもの。

これをFileSystem.writeAsStringAsyncで保存した状態で、Sharing.shareAsyncによってユーザーの好きなメディアにエクスポートできるようになっています。

今回はエクスポートが目的で、アプリにファイルを保存したいわけではないので、最後に削除する一文を足しています。

 

 

おわりに

ちなみに自分は未だに非同期処理を書きなれていないので、はじめの方で引用していたpermissionを挟んでいた事例に従って書いたこのasync awaitの書き方に意味があるのかは分かりません。

 

まぁともかく、React native + ExpoでもJSON/stringからなるデータであれば結構シンプルにcsv化してエクスポートできるよ!という記事でした。