электронный лист загружает сгенерированный файл из JSON

У меня есть приложение Electron с VueJS, и я пытаюсь загрузить сгенерированный XLS с помощью sheetjs, но при условии обходной путь не работает в моем случае. Вот что я пытался:

 exportData(id, type) {
      // eslint-disable-next-line no-console
      console.log(type);

      (async () => {
        const data = await ProjectController.getProject(id);
        const ws = XLSX.utils.json_to_sheet(JSON.parse(data.excel));
        // eslint-disable-next-line no-console

        let wb = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(wb, ws, "test");
        let o = dialog.showSaveDialog();
        // eslint-disable-next-line no-console
        console.log(o);

        XLSX.writeFile(wb, o);

        // eslint-disable-next-line no-console
        //console.log(file);
      })();
    }

В консоли я получаю следующую ошибку Uncaught (in promise) TypeError: o.file.lastIndexOf is not a function.

если я использую следующий код

  (async () => {
        const data = await ProjectController.getProject(id);

        const ws = (XLSX.WorkSheet = XLSX.utils.json_to_sheet(
          JSON.parse(data.excel)
        ));

        let wb = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(wb, ws, "test");


        const file = XLSX.write(wb, {
          bookType: "xlsx",
          type: "buffer",
          compression: true
        });

        let savePath = dialog.showSaveDialog({});
        XLSX.writeFile(file, savePath);

        fs.writeFileSync("test1.xlsx", file);


      })();

чем файл будет загружен в корень папки проекта без всплывающих окон. Но я хотел бы иметь возможность загружать эти файлы в выбранную пользователем папку.

вот мой package.json

{
  "name": "movie-translation-tool",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "electron:build": "vue-cli-service electron:build",
    "electron:serve": "vue-cli-service electron:serve",
    "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps"
  },
  "main": "background.js",
  "dependencies": {
    "awesome-phonenumber": "^2.24.0",
    "core-js": "^3.4.3",
    "dropbox": "^4.0.30",
    "knex": "^0.20.3",
    "mssql": "^6.0.1",
    "objection": "^2.0.3",
    "pdf2json": "^1.2.0",
    "sqlite3": "^4.1.1",
    "vee-validate": "^3.1.3",
    "vue": "^2.6.10",
    "vue-i18n": "^8.0.0",
    "vue-router": "^3.1.3",
    "vue-video-player": "^5.0.2",
    "vuetify": "^2.1.0",
    "vuetify-image-input": "^19.1.0",
    "vuex": "^3.1.2",
    "xlsx": "^0.15.3"
  },
  "devDependencies": {
    "@mdi/font": "^4.6.95",
    "@mdi/js": "^4.6.95",
    "@vue/cli-plugin-babel": "^4.1.0",
    "@vue/cli-plugin-eslint": "^4.1.0",
    "@vue/cli-plugin-router": "^4.1.1",
    "@vue/cli-plugin-vuex": "^4.1.1",
    "@vue/cli-service": "^4.1.0",
    "babel-eslint": "^10.0.3",
    "electron": "^6.0.0",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "material-design-icons-iconfont": "^5.0.1",
    "sass": "^1.19.0",
    "sass-loader": "^10.0.0",
    "vue-cli-plugin-electron-builder": "^1.4.3",
    "vue-cli-plugin-i18n": "^0.6.1",
    "vue-cli-plugin-vuetify": "^2.0.2",
    "vue-template-compiler": "^2.6.10",
    "vuetify-loader": "^1.3.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "rules": {},
    "parserOptions": {
      "parser": "babel-eslint"
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

Как правильно прикрепить файл к винде?


person fefe    schedule 17.03.2020    source источник
comment
Появляется диалоговое окно сохранения? Где вы используете эту функцию, в основном процессе или в процессе рендерера? Кроме того, пожалуйста, обновите содержимое package.json.   -  person Christos Lytras    schedule 23.03.2020
comment
в первом примере у меня есть всплывающее окно, но ничего не сохраняется, во втором фрагменте кода у меня нет всплывающего окна, и файл сохраняется в корне моего проекта. На самом деле exportData — это метод VUE, который запускается при нажатии кнопки.   -  person fefe    schedule 23.03.2020
comment
Пожалуйста, проверьте мой ответ и дайте мне знать, работает ли он для вас.   -  person Christos Lytras    schedule 23.03.2020


Ответы (1)


Метод диалога dialog.showSaveDialog возвращает обещание, которое разрешается в объект, это не возвращает строку:

dialog.showSaveDialog([browserWindow, ]options)

Возвращает Promise<Object> — разрешить объект, содержащий следующее:

  • canceled Boolean - был ли диалог отменен.
  • filePath Строка (необязательно) — если диалоговое окно отменено, это будет undefined.
  • bookmark Строка (необязательно) macOS mas — строка в кодировке Base64, содержащая данные закладок с областью безопасности для сохраненного файла. securityScopedBookmarks должен быть включен, чтобы это присутствовало. (Возвращаемые значения см. в таблице здесь.)

Вы должны await для dialog.showSaveDialog или использовать dialog.showSaveDialogSync, а также вы можете сделать exportData асинхронным, а не создавать внутреннюю асинхронную функцию.

Попробуйте реорганизовать свой код следующим образом:

async exportData(id, type) {
  const data = await ProjectController.getProject(id);
  const ws = XLSX.utils.json_to_sheet(JSON.parse(data.excel));
  const wb = XLSX.utils.book_new();

  XLSX.utils.book_append_sheet(wb, ws, "test");

  let { filePath, canceled } = await dialog.showSaveDialog();

  if (!canceled) {
    XLSX.writeFile(wb, filePath);
  }
}
person Christos Lytras    schedule 23.03.2020
comment
Большое спасибо! Хорошо работает с рефакторингом. Можно ли подтолкнуть данное имя файла к всплывающему окну? - person fefe; 23.03.2020
comment
Да, вы можете использовать свойство опции defaultPath, чтобы установить предлагаемое имя файла или даже путь к диалоговому окну (например, await dialog.showSaveDialog(null, { defaultPath: "Project-data.xls" })). defaultPath Строка (необязательно) — абсолютный путь к каталогу, абсолютный путь к файлу или имя файла для использования по умолчанию. - person Christos Lytras; 23.03.2020