w-html2docx 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +55 -0
- package/.jsdoc +25 -0
- package/LICENSE +21 -0
- package/README.md +52 -0
- package/SECURITY.md +5 -0
- package/babel.config.js +16 -0
- package/dist/w-html2docx.umd.js +7 -0
- package/dist/w-html2docx.umd.js.map +1 -0
- package/docs/WHtml2docx.mjs.html +234 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/global.html +486 -0
- package/docs/index.html +84 -0
- package/docs/scripts/collapse.js +39 -0
- package/docs/scripts/commonNav.js +28 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/nav.js +12 -0
- package/docs/scripts/polyfill.js +4 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/scripts/search.js +99 -0
- package/docs/styles/jsdoc.css +776 -0
- package/docs/styles/prettify.css +80 -0
- package/g.mjs +26 -0
- package/package.json +32 -0
- package/script.txt +17 -0
- package/scripts/install.mjs +30 -0
- package/src/WHtml2docx.mjs +162 -0
- package/src/downloadFiles.mjs +23 -0
- package/src/tmp.docx +0 -0
- package/srcPython/build.bat +9 -0
- package/srcPython/htmlToDocx.py +239 -0
- package/srcPython/htmlToDocx.spec +37 -0
- package/srcPython/run.bat +4 -0
- package/srcPython//350/252/252/346/230/216.txt +24 -0
- package/test/WHtml2docx.test.mjs +35 -0
- package/test/ztmp.html +319 -0
- package/test/ztmpTrue.docx +0 -0
- package/toolg/addVersion.mjs +4 -0
- package/toolg/cleanFolder.mjs +4 -0
- package/toolg/gDistRollup.mjs +28 -0
- package/toolg/modifyReadme.mjs +4 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
.pln {
|
|
2
|
+
color: #ddd;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* string content */
|
|
6
|
+
.str {
|
|
7
|
+
color: #61ce3c;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* a keyword */
|
|
11
|
+
.kwd {
|
|
12
|
+
color: #fbde2d;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* a comment */
|
|
16
|
+
.com {
|
|
17
|
+
color: #aeaeae;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* a type name */
|
|
21
|
+
.typ {
|
|
22
|
+
color: #8da6ce;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* a literal value */
|
|
26
|
+
.lit {
|
|
27
|
+
color: #fbde2d;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* punctuation */
|
|
31
|
+
.pun {
|
|
32
|
+
color: #ddd;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* lisp open bracket */
|
|
36
|
+
.opn {
|
|
37
|
+
color: #000000;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* lisp close bracket */
|
|
41
|
+
.clo {
|
|
42
|
+
color: #000000;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* a markup tag name */
|
|
46
|
+
.tag {
|
|
47
|
+
color: #8da6ce;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* a markup attribute name */
|
|
51
|
+
.atn {
|
|
52
|
+
color: #fbde2d;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* a markup attribute value */
|
|
56
|
+
.atv {
|
|
57
|
+
color: #ddd;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* a declaration */
|
|
61
|
+
.dec {
|
|
62
|
+
color: #EF5050;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* a variable name */
|
|
66
|
+
.var {
|
|
67
|
+
color: #c82829;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* a function name */
|
|
71
|
+
.fun {
|
|
72
|
+
color: #4271ae;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Specify class=linenums on a pre to get line numbering */
|
|
76
|
+
ol.linenums {
|
|
77
|
+
margin-top: 0;
|
|
78
|
+
margin-bottom: 0;
|
|
79
|
+
padding-bottom: 2px;
|
|
80
|
+
}
|
package/g.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import w from 'wsemi'
|
|
2
|
+
import WHtml2docx from './src/WHtml2docx.mjs'
|
|
3
|
+
//import WHtml2docx from 'w-html2docx/src/WHtml2docx.mjs'
|
|
4
|
+
//import WHtml2docx from 'w-html2docx'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async function test() {
|
|
8
|
+
|
|
9
|
+
let fpIn = `./test/ztmp.html`
|
|
10
|
+
let fpOut = `./test/ztmp.docx`
|
|
11
|
+
let opt = {}
|
|
12
|
+
|
|
13
|
+
let r = await WHtml2docx(fpIn, fpOut, opt)
|
|
14
|
+
console.log(r)
|
|
15
|
+
// => ok
|
|
16
|
+
|
|
17
|
+
w.fsDeleteFile(fpOut)
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
test()
|
|
21
|
+
.catch((err) => {
|
|
22
|
+
console.log('catch', err)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
//node g.mjs
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "w-html2docx",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/w-html2docx.umd.js",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"lodash-es": "^4.17.21",
|
|
7
|
+
"wsemi": "^1.8.34"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"w-package-tools": "^1.1.2"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"postinstall": "node scripts/install.mjs",
|
|
14
|
+
"test": "mocha --parallel --timeout 60000",
|
|
15
|
+
"deploy": "gh-pages -d docs"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/yuda-lyu/w-html2docx.git"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"package",
|
|
23
|
+
"tool",
|
|
24
|
+
"win32com",
|
|
25
|
+
"html",
|
|
26
|
+
"docx",
|
|
27
|
+
"windows",
|
|
28
|
+
"nodejs"
|
|
29
|
+
],
|
|
30
|
+
"author": "yuda-lyu(semisphere)",
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|
package/script.txt
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#node toolg/addVersion.mjs
|
|
2
|
+
node toolg/modifyReadme.mjs
|
|
3
|
+
|
|
4
|
+
node toolg/cleanFolder.mjs
|
|
5
|
+
./node_modules/.bin/jsdoc -c .jsdoc
|
|
6
|
+
|
|
7
|
+
node toolg/gDistRollup.mjs
|
|
8
|
+
|
|
9
|
+
git add . -A
|
|
10
|
+
git commit -m 'modify: '
|
|
11
|
+
git push origin master:master
|
|
12
|
+
|
|
13
|
+
npm run deploy
|
|
14
|
+
|
|
15
|
+
#npm test
|
|
16
|
+
|
|
17
|
+
#npm publish
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { fileURLToPath } from 'url'
|
|
3
|
+
import downloadFiles from '../src/downloadFiles.mjs'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async function init() {
|
|
7
|
+
|
|
8
|
+
//check, 被安裝條件才執行
|
|
9
|
+
let __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
10
|
+
if (!__dirname.includes('node_modules')) {
|
|
11
|
+
return //非位於node_modules, 代表套件本身
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//fdSrv
|
|
15
|
+
let fdSrv = path.resolve()
|
|
16
|
+
|
|
17
|
+
//fdBase,
|
|
18
|
+
let fdBase = `${fdSrv}/src/` //npm i後觸發安裝時, 工作路徑是位於套件內
|
|
19
|
+
// console.log('fdBase', fdBase)
|
|
20
|
+
|
|
21
|
+
//downloadFiles
|
|
22
|
+
await downloadFiles(fdBase)
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
init()
|
|
26
|
+
.catch((err) => {
|
|
27
|
+
console.log(err)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
//node scripts/install.mjs
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import process from 'process'
|
|
3
|
+
import get from 'lodash-es/get.js'
|
|
4
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
5
|
+
import isearr from 'wsemi/src/isearr.mjs'
|
|
6
|
+
import cstr from 'wsemi/src/cstr.mjs'
|
|
7
|
+
import str2b64 from 'wsemi/src/str2b64.mjs'
|
|
8
|
+
import execProcess from 'wsemi/src/execProcess.mjs'
|
|
9
|
+
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
let fdSrv = path.resolve()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function isWindows() {
|
|
16
|
+
return process.platform === 'win32'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Html檔轉Docx檔
|
|
22
|
+
*
|
|
23
|
+
* @param {String} fpInHtml 輸入來源Html檔位置字串
|
|
24
|
+
* @param {String} fpOutDocx 輸入轉出Docx檔位置字串
|
|
25
|
+
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
26
|
+
* @param {Array|String} [opt.fontFamilies=['標楷體', 'Times New Roman']] 輸入Docx更改字型陣列或字串,預設['標楷體', 'Times New Roman']
|
|
27
|
+
* @returns {Promise} 回傳Promise,resolve回傳成功訊息,reject回傳錯誤訊息
|
|
28
|
+
* @example
|
|
29
|
+
*
|
|
30
|
+
* import w from 'wsemi'
|
|
31
|
+
* import WHtml2docx from './src/WHtml2docx.mjs'
|
|
32
|
+
* //import WHtml2docx from 'w-html2docx/src/WHtml2docx.mjs'
|
|
33
|
+
* //import WHtml2docx from 'w-html2docx'
|
|
34
|
+
*
|
|
35
|
+
* async function test() {
|
|
36
|
+
*
|
|
37
|
+
* let fpIn = `./test/ztmp.html`
|
|
38
|
+
* let fpOut = `./test/ztmp.docx`
|
|
39
|
+
* let opt = {}
|
|
40
|
+
*
|
|
41
|
+
* let r = await WHtml2docx(fpIn, fpOut, opt)
|
|
42
|
+
* console.log(r)
|
|
43
|
+
* // => ok
|
|
44
|
+
*
|
|
45
|
+
* w.fsDeleteFile(fpOut)
|
|
46
|
+
*
|
|
47
|
+
* }
|
|
48
|
+
* test()
|
|
49
|
+
* .catch((err) => {
|
|
50
|
+
* console.log('catch', err)
|
|
51
|
+
* })
|
|
52
|
+
*
|
|
53
|
+
*/
|
|
54
|
+
async function WHtml2docx(fpInHtml, fpOutDocx, opt = {}) {
|
|
55
|
+
let errTemp = null
|
|
56
|
+
|
|
57
|
+
//isWindows
|
|
58
|
+
if (!isWindows()) {
|
|
59
|
+
return Promise.reject('operating system is not windows')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//check
|
|
63
|
+
if (!fsIsFile(fpInHtml)) {
|
|
64
|
+
return Promise.reject(`fpInHtml[${fpInHtml}] does not exist`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//轉絕對路徑
|
|
68
|
+
fpInHtml = path.resolve(fpInHtml)
|
|
69
|
+
fpOutDocx = path.resolve(fpOutDocx)
|
|
70
|
+
|
|
71
|
+
//fontFamilies
|
|
72
|
+
let fontFamilies = get(opt, 'fontFamilies')
|
|
73
|
+
if (isestr(fontFamilies)) {
|
|
74
|
+
fontFamilies = [fontFamilies]
|
|
75
|
+
}
|
|
76
|
+
if (!isearr(fontFamilies)) {
|
|
77
|
+
fontFamilies = ['標楷體', 'Times New Roman']
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//fnTmp
|
|
81
|
+
let fnTmp = `tmp.docx`
|
|
82
|
+
|
|
83
|
+
//fpTmp
|
|
84
|
+
let fpTmp = ``
|
|
85
|
+
if (true) {
|
|
86
|
+
let fpTmpSrc = `${fdSrv}/src/${fnTmp}`
|
|
87
|
+
let fpTmpNM = `${fdSrv}/node_modules/w-html2docx/src/${fnTmp}`
|
|
88
|
+
if (fsIsFile(fpTmpSrc)) {
|
|
89
|
+
fpTmp = fpTmpSrc
|
|
90
|
+
}
|
|
91
|
+
else if (fsIsFile(fpTmpNM)) {
|
|
92
|
+
fpTmp = fpTmpNM
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return Promise.reject(`can not find folder for ${fnTmp}`)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//轉絕對路徑
|
|
99
|
+
fpTmp = path.resolve(fpTmp)
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//fnExe
|
|
104
|
+
let fnExe = `htmlToDocx.exe`
|
|
105
|
+
|
|
106
|
+
//fdExe
|
|
107
|
+
let fdExe = ''
|
|
108
|
+
if (true) {
|
|
109
|
+
let fdExeSrc = `${fdSrv}/src/`
|
|
110
|
+
let fdExeNM = `${fdSrv}/node_modules/w-html2docx/src/`
|
|
111
|
+
if (fsIsFile(`${fdExeSrc}${fnExe}`)) {
|
|
112
|
+
fdExe = fdExeSrc
|
|
113
|
+
}
|
|
114
|
+
else if (fsIsFile(`${fdExeNM}${fnExe}`)) {
|
|
115
|
+
fdExe = fdExeNM
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return Promise.reject('can not find folder for html2docx')
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// console.log('fdExe', fdExe)
|
|
122
|
+
|
|
123
|
+
//prog
|
|
124
|
+
let prog = `${fdExe}${fnExe}`
|
|
125
|
+
// console.log('prog', prog)
|
|
126
|
+
|
|
127
|
+
//inp
|
|
128
|
+
let inp = {
|
|
129
|
+
fpInSrc: fpInHtml,
|
|
130
|
+
fpInTemp: fpTmp,
|
|
131
|
+
fpOut: fpOutDocx,
|
|
132
|
+
fontFamilies: ['標楷體', 'Times New Roman'],
|
|
133
|
+
}
|
|
134
|
+
// console.log('inp', inp)
|
|
135
|
+
|
|
136
|
+
//input to b64
|
|
137
|
+
let cInput = JSON.stringify(inp)
|
|
138
|
+
let b64Input = str2b64(cInput)
|
|
139
|
+
// console.log('b64Input', b64Input)
|
|
140
|
+
|
|
141
|
+
//execProcess
|
|
142
|
+
await execProcess(prog, b64Input)
|
|
143
|
+
.catch((err) => {
|
|
144
|
+
console.log('execProcess catch', err)
|
|
145
|
+
errTemp = err.toString()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
//check
|
|
149
|
+
if (errTemp) {
|
|
150
|
+
return Promise.reject(errTemp)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// //check
|
|
154
|
+
// if (!isestr(output)) {
|
|
155
|
+
// return Promise.reject(`output[${cstr(output)}] is not an effective string`)
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
return 'ok'
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
export default WHtml2docx
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fsDownloadFile from 'wsemi/src/fsDownloadFile.mjs'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
async function downloadFiles(fdBase) {
|
|
5
|
+
|
|
6
|
+
//url
|
|
7
|
+
let url = `https://github.com/yuda-lyu/w-html2docx/raw/refs/heads/master/src/htmlToDocx.exe`
|
|
8
|
+
// console.log('url',url)
|
|
9
|
+
|
|
10
|
+
//fn
|
|
11
|
+
let fn = `htmlToDocx.exe`
|
|
12
|
+
|
|
13
|
+
//fp
|
|
14
|
+
let fp = `${fdBase}${fn}`
|
|
15
|
+
|
|
16
|
+
//fsDownloadFile
|
|
17
|
+
console.log(`downloading url[${url}]...`, `to fp[${fp}]`)
|
|
18
|
+
await fsDownloadFile(url, fp)
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export default downloadFiles
|
package/src/tmp.docx
ADDED
|
Binary file
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
from win32com import client as wc
|
|
2
|
+
|
|
3
|
+
#使用win32com
|
|
4
|
+
#win32com因更新問題會出現 ImportError: DLL load failed while importing win32api: 找不到指定的模組。
|
|
5
|
+
#1. 安裝 pip install pywin32
|
|
6
|
+
#2. 使用系統管理員權限開啟cmd
|
|
7
|
+
#3. cd至安裝目錄 C:\ProgramData\Anaconda3\Scripts
|
|
8
|
+
#4. 用python安裝腳本 python pywin32_postinstall.py -install
|
|
9
|
+
|
|
10
|
+
#編譯
|
|
11
|
+
#1. 安裝編譯套件 pip install pyinstaller
|
|
12
|
+
#2. 編譯 pyinstaller -F htmlToDocx.py
|
|
13
|
+
|
|
14
|
+
#win32com教學
|
|
15
|
+
#https://zhuanlan.zhihu.com/p/67543981
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def getError():
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
#exc_info
|
|
22
|
+
type, message, traceback = sys.exc_info()
|
|
23
|
+
|
|
24
|
+
#es
|
|
25
|
+
es=[]
|
|
26
|
+
while traceback:
|
|
27
|
+
e={
|
|
28
|
+
'name':traceback.tb_frame.f_code.co_name,
|
|
29
|
+
'filename':traceback.tb_frame.f_code.co_filename,
|
|
30
|
+
}
|
|
31
|
+
es.append(e)
|
|
32
|
+
traceback = traceback.tb_next
|
|
33
|
+
|
|
34
|
+
#err
|
|
35
|
+
err={
|
|
36
|
+
'type':type,
|
|
37
|
+
'message':message,
|
|
38
|
+
'traceback':es,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return err
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def j2o(v):
|
|
45
|
+
#json轉物件
|
|
46
|
+
import json
|
|
47
|
+
return json.loads(v)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def o2j(v):
|
|
51
|
+
#物件轉json
|
|
52
|
+
import json
|
|
53
|
+
return json.dumps(v, ensure_ascii=False)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def str2b64(v):
|
|
57
|
+
#字串轉base64字串
|
|
58
|
+
import base64
|
|
59
|
+
v=base64.b64encode(v.encode('utf-8'))
|
|
60
|
+
return str(v,'utf-8')
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def b642str(v):
|
|
64
|
+
#base64字串轉字串
|
|
65
|
+
import base64
|
|
66
|
+
return base64.b64decode(v)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def readText(fn):
|
|
70
|
+
#讀取檔案fn內文字
|
|
71
|
+
import codecs
|
|
72
|
+
with codecs.open(fn,'r',encoding='utf8') as f:
|
|
73
|
+
return f.read()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def writeText(fn,str):
|
|
77
|
+
#寫出文字str至檔案fn
|
|
78
|
+
import codecs
|
|
79
|
+
with codecs.open(fn,'w',encoding='utf8') as f:
|
|
80
|
+
f.write(str)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def htmlToDocx(fpInSrc, fpInTemp, fpOut, opt):
|
|
84
|
+
|
|
85
|
+
#Dispatch
|
|
86
|
+
app = wc.Dispatch('Word.Application')
|
|
87
|
+
|
|
88
|
+
#正式版須隱藏
|
|
89
|
+
app.Visible = False #True False
|
|
90
|
+
|
|
91
|
+
#不詢問使用者
|
|
92
|
+
app.DisplayAlerts = False
|
|
93
|
+
|
|
94
|
+
#Open
|
|
95
|
+
docInTemp = app.Documents.Open(fpInTemp)
|
|
96
|
+
docInSrc = app.Documents.Open(fpInSrc)
|
|
97
|
+
|
|
98
|
+
#選擇src並複製全文
|
|
99
|
+
docInSrc.Activate()
|
|
100
|
+
app.Selection.WholeStory()
|
|
101
|
+
app.Selection.Copy()
|
|
102
|
+
|
|
103
|
+
#選擇模板並貼上全文
|
|
104
|
+
docInTemp.Activate()
|
|
105
|
+
app.Selection.Paste()
|
|
106
|
+
# WdFormatOriginalFormatting = 16
|
|
107
|
+
# app.Selection.PasteAndFormat(WdFormatOriginalFormatting)
|
|
108
|
+
|
|
109
|
+
#選擇模板調整字型
|
|
110
|
+
try:
|
|
111
|
+
fontFamilies=opt['fontFamilies']
|
|
112
|
+
if hasattr(fontFamilies, "__len__"):
|
|
113
|
+
if len(fontFamilies)>0:
|
|
114
|
+
#print(fontFamilies)
|
|
115
|
+
docInTemp.Activate()
|
|
116
|
+
app.Selection.WholeStory()
|
|
117
|
+
for fn in fontFamilies:
|
|
118
|
+
# print(fn)
|
|
119
|
+
app.Selection.Font.Name = fn
|
|
120
|
+
except:
|
|
121
|
+
err=getError()
|
|
122
|
+
print(err)
|
|
123
|
+
|
|
124
|
+
#選擇模板偵測各圖片寬度是否大於滿版(412), 並限制於最大值
|
|
125
|
+
try:
|
|
126
|
+
docInTemp.Activate()
|
|
127
|
+
app.Selection.WholeStory()
|
|
128
|
+
#print(len(app.Selection.Range.InlineShapes)) #有幾張圖
|
|
129
|
+
for s in app.Selection.Range.InlineShapes:
|
|
130
|
+
try:
|
|
131
|
+
s.LockAspectRatio = True
|
|
132
|
+
#240 -> 8.47公分 max=14.55公分
|
|
133
|
+
if s.Width > 412:
|
|
134
|
+
s.Width = 412
|
|
135
|
+
except:
|
|
136
|
+
err = getError()
|
|
137
|
+
print(err)
|
|
138
|
+
|
|
139
|
+
except:
|
|
140
|
+
err=getError()
|
|
141
|
+
print(err)
|
|
142
|
+
|
|
143
|
+
#SaveAs
|
|
144
|
+
WdSaveFormat = 16 # wdFormatDocumentDefault=16(docx) #https://learn.microsoft.com/zh-tw/office/vba/api/word.wdsaveformat
|
|
145
|
+
docInTemp.SaveAs2(fpOut, WdSaveFormat)
|
|
146
|
+
|
|
147
|
+
# Close
|
|
148
|
+
WdDoNotSaveChanges = 0 # wdDoNotSaveChanges
|
|
149
|
+
docInTemp.Close(WdDoNotSaveChanges)
|
|
150
|
+
docInSrc.Close(WdDoNotSaveChanges)
|
|
151
|
+
|
|
152
|
+
#Quit
|
|
153
|
+
WdSaveOptions = 0 #wdDoNotSaveChanges=0(不儲存擱置中變更) #https://learn.microsoft.com/zh-tw/office/vba/api/word.wdsaveoptions
|
|
154
|
+
app.Quit(WdSaveOptions)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def core(b64):
|
|
158
|
+
state=''
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
|
|
162
|
+
#b642str
|
|
163
|
+
s=b642str(b64)
|
|
164
|
+
|
|
165
|
+
#j2o
|
|
166
|
+
o=j2o(s)
|
|
167
|
+
|
|
168
|
+
#params
|
|
169
|
+
fpInSrc=o['fpInSrc']
|
|
170
|
+
fpInTemp=o['fpInTemp']
|
|
171
|
+
fpOut=o['fpOut']
|
|
172
|
+
|
|
173
|
+
#opt
|
|
174
|
+
opt={}
|
|
175
|
+
opt['fontFamilies']=o['fontFamilies']
|
|
176
|
+
|
|
177
|
+
#htmlToDocx
|
|
178
|
+
htmlToDocx(fpInSrc, fpInTemp, fpOut, opt)
|
|
179
|
+
|
|
180
|
+
state='success'
|
|
181
|
+
except:
|
|
182
|
+
err=getError()
|
|
183
|
+
state='error: '+str(err["message"])
|
|
184
|
+
|
|
185
|
+
return state
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def run():
|
|
189
|
+
import sys
|
|
190
|
+
|
|
191
|
+
#由外部程序呼叫或直接給予檔案路徑
|
|
192
|
+
state=''
|
|
193
|
+
argv=sys.argv
|
|
194
|
+
#argv=['','']
|
|
195
|
+
if len(argv)==2:
|
|
196
|
+
|
|
197
|
+
#b64
|
|
198
|
+
b64=sys.argv[1]
|
|
199
|
+
|
|
200
|
+
#core
|
|
201
|
+
state=core(b64)
|
|
202
|
+
|
|
203
|
+
else:
|
|
204
|
+
#print(sys.argv)
|
|
205
|
+
state='error: invalid length of argv'
|
|
206
|
+
|
|
207
|
+
#print & flush
|
|
208
|
+
print(state)
|
|
209
|
+
sys.stdout.flush()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
if True:
|
|
213
|
+
#正式版
|
|
214
|
+
|
|
215
|
+
#run
|
|
216
|
+
run()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if False:
|
|
220
|
+
#產生測試輸入b64
|
|
221
|
+
|
|
222
|
+
#inp
|
|
223
|
+
inp={
|
|
224
|
+
'fpInSrc':'./ztmp.html',
|
|
225
|
+
'fpInTemp':'./tmp.docx',
|
|
226
|
+
'fpOut':'./ztmp.docx',
|
|
227
|
+
'fontFamilies': ['標楷體','Times New Roman'], #word使用, 因由左往右設定, 故得先設定標楷體再設定Times New Roman
|
|
228
|
+
}
|
|
229
|
+
# print(o2j(inp))
|
|
230
|
+
|
|
231
|
+
#str2b64
|
|
232
|
+
b64=str2b64(o2j(inp))
|
|
233
|
+
print(b64)
|
|
234
|
+
|
|
235
|
+
#core
|
|
236
|
+
state=core(b64)
|
|
237
|
+
|
|
238
|
+
print(state)
|
|
239
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- mode: python ; coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
a = Analysis(
|
|
5
|
+
['htmlToDocx.py'],
|
|
6
|
+
pathex=[],
|
|
7
|
+
binaries=[],
|
|
8
|
+
datas=[],
|
|
9
|
+
hiddenimports=[],
|
|
10
|
+
hookspath=[],
|
|
11
|
+
hooksconfig={},
|
|
12
|
+
runtime_hooks=[],
|
|
13
|
+
excludes=[],
|
|
14
|
+
noarchive=False,
|
|
15
|
+
)
|
|
16
|
+
pyz = PYZ(a.pure)
|
|
17
|
+
|
|
18
|
+
exe = EXE(
|
|
19
|
+
pyz,
|
|
20
|
+
a.scripts,
|
|
21
|
+
a.binaries,
|
|
22
|
+
a.datas,
|
|
23
|
+
[],
|
|
24
|
+
name='htmlToDocx',
|
|
25
|
+
debug=False,
|
|
26
|
+
bootloader_ignore_signals=False,
|
|
27
|
+
strip=False,
|
|
28
|
+
upx=True,
|
|
29
|
+
upx_exclude=[],
|
|
30
|
+
runtime_tmpdir=None,
|
|
31
|
+
console=True,
|
|
32
|
+
disable_windowed_traceback=False,
|
|
33
|
+
argv_emulation=False,
|
|
34
|
+
target_arch=None,
|
|
35
|
+
codesign_identity=None,
|
|
36
|
+
entitlements_file=None,
|
|
37
|
+
)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
python htmlToDocx.py eyJmcEluU3JjIjogIkQ6XFwtIDAwNiAtICAgICAgICDplovmupBcXOmWi+a6kC1KUy0wMDgtNC13LWh0bWwyZG9jeFxcdy1odG1sMmRvY3hcXHNyY1B5dGhvblxcenRtcC5odG1sIiwgImZwSW5UZW1wIjogIkQ6XFwtIDAwNiAtICAgICAgICDplovmupBcXOmWi+a6kC1KUy0wMDgtNC13LWh0bWwyZG9jeFxcdy1odG1sMmRvY3hcXHNyY1B5dGhvblxcdG1wLmRvY3giLCAiZnBPdXQiOiAiRDpcXC0gMDA2IC0gICAgICAgIOmWi+a6kFxc6ZaL5rqQLUpTLTAwOC00LXctaHRtbDJkb2N4XFx3LWh0bWwyZG9jeFxcc3JjUHl0aG9uXFx6dG1wLmRvY3giLCAiZm9udEZhbWlsaWVzIjogWyLmqJnmpbfpq5QiLCAiVGltZXMgTmV3IFJvbWFuIl19
|
|
2
|
+
pause
|
|
3
|
+
|
|
4
|
+
#測試版使用
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
0.可用pyinstaller或nuitka編譯,但nuitka編譯出檔案會小一點(4x mb),不過卻無法執行待研究
|
|
3
|
+
|
|
4
|
+
1.可先用一般編譯方式產生spec檔: pyinstaller -F htmlToDocx.py,就會產生htmlToDocx.spec
|
|
5
|
+
|
|
6
|
+
2.若有需要修改spec後,編譯指令改為對spec檔編譯: pyinstaller build.spec
|
|
7
|
+
|
|
8
|
+
3.使用build.bat進行編譯
|
|
9
|
+
|
|
10
|
+
8.編譯完複製htmlToDocx.exe至bin,使用bin\run.bat執行,傳入的b64可將物件
|
|
11
|
+
{
|
|
12
|
+
'fpIn':'input.html',
|
|
13
|
+
'fpOut':'output.docx'
|
|
14
|
+
}
|
|
15
|
+
序列化成字串再轉base64即可
|
|
16
|
+
|
|
17
|
+
----------------------------------------------------------------------
|
|
18
|
+
參考
|
|
19
|
+
|
|
20
|
+
解决方法:pyinstaller打包缺文件
|
|
21
|
+
https://www.geek-share.com/detail/2773482967.html
|
|
22
|
+
|
|
23
|
+
pyinstaller spec文件
|
|
24
|
+
https://pyinstaller.readthedocs.io/en/stable/spec-files.html
|