Skip to content

Commit 03e480f

Browse files
author
Junhui Tong
committed
worked build
1 parent 4623ad6 commit 03e480f

File tree

7 files changed

+61
-15
lines changed

7 files changed

+61
-15
lines changed

backend/api_impl.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import * as wui from "https://win32.deno.dev/0.4.1/UI.WindowsAndMessaging"
22
import { BackendAPI } from '../api.ts'
3+
import staticAssets from '../static_assets.json' with { type: "json" }
34

45
let scriptProcess: Deno.ChildProcess
56

7+
const infoFile = Deno.env.get('TEMP') + '\\excel_info.txt'
68
function launchScript() {
9+
// check if excel.js is present
10+
let scriptFile = `./excel.js`
11+
try {
12+
Deno.statSync(scriptFile)
13+
} catch (_e) {
14+
scriptFile = Deno.env.get('TEMP') + '\\excel.js'
15+
const content = staticAssets['./excel.js']
16+
Deno.writeTextFileSync(scriptFile, content)
17+
}
718
const cmd = new Deno.Command('cscript.exe', {
8-
args: ['//nologo', 'excel.js'],
19+
args: ['//nologo', scriptFile, infoFile],
920
stdout: 'inherit',
1021
stderr: 'inherit',
1122
})
@@ -60,7 +71,7 @@ export const apiImpl: BackendAPI = {
6071
},
6172
getActiveExcelRow: async () => {
6273
// read output from script
63-
const s = Deno.readTextFileSync('excelrow.txt')
74+
const s = Deno.readTextFileSync(infoFile)
6475
const [hs, vs] = s.split('_@@RS@@_')
6576
return {
6677
headings: hs.split('_@@HS@@_'),

build.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// wrap some static assest to a single json file
2+
// so that they are be imported to main app and can be created on demand on a http import use case
3+
4+
const htmlContent = Deno.readTextFileSync('./frontend/dist/index.html')
5+
const jsContent = Deno.readTextFileSync('./frontend/dist/assets/index.js')
6+
7+
// replace content within <!--SCRIPT-START--> and <!--SCRIPT-END--> to jsContent
8+
const newHtmlContent = htmlContent.replace(/<!--SCRIPT-START-->[\s\S]*<!--SCRIPT-END-->/, `<!--SCRIPT-START-->\n<script type="module">\n${jsContent}\n</script>\n<!--SCRIPT-END-->`)
9+
10+
const wshScriptContent = Deno.readTextFileSync('./excel.js')
11+
12+
const staticAssets = {
13+
'/index.html': newHtmlContent,
14+
'/index2.html': newHtmlContent,
15+
'excel.js': wshScriptContent,
16+
}
17+
18+
Deno.writeTextFileSync('./static_assets.json', JSON.stringify(staticAssets, null, 2))

dwa/dwa_service.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { typeByExtension } from "https://deno.land/std/media_types/mod.ts";
22
import { extname } from "https://deno.land/std/path/mod.ts";
3+
import staticAssets from '../static_assets.json' with { type: "json" }
34

45
export function startDenoWebApp(root: string, port: number, apiImpl: {[key: string]: Function}) {
56
const corsHeaders = {
@@ -49,6 +50,14 @@ export function startDenoWebApp(root: string, port: number, apiImpl: {[key: stri
4950
});
5051
} catch(ex){
5152
if(ex.code === "ENOENT"){
53+
// check from static assets
54+
if (path in staticAssets) {
55+
return new Response(staticAssets[path as keyof typeof staticAssets], {
56+
headers: {
57+
"content-type" : typeByExtension(extname(path)) || "text/plain"
58+
}
59+
});
60+
}
5261
return new Response("Not Found", { status: 404 });
5362
}
5463
return new Response("Internal Server Error", { status: 500 });

excel.js

+5-13
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,12 @@ function WriteTextFile (text, path, encoding) {
77
if (encoding) stream.Charset = encoding;
88
stream.Open();
99
stream.Position = 0;
10-
1110
stream.WriteText(text);
12-
try {
13-
fso.CreateFolder(tps.file.GetDir(path));
14-
} catch (e) { }
1511
stream.SaveToFile(path, 2);
16-
1712
stream.Close();
1813
}
1914

20-
function saveActiveRow(excel) {
15+
function saveActiveRow(excel, path) {
2116
var sheet = excel.ActiveSheet;
2217
if (sheet) {
2318
// get max column that have data
@@ -38,28 +33,25 @@ function saveActiveRow(excel) {
3833
var rowValues = rowValues.join('_@@VS@@_');
3934
var content = [headings, rowValues].join('_@@RS@@_');
4035
WScript.Echo(content);
41-
WriteTextFile(content, 'excelrow.txt', 'utf-8');
36+
WriteTextFile(content, path, 'utf-8');
4237
}
4338
}
4439
}
4540

4641
var excel = new ActiveXObject('Excel.Application');
4742
excel.Visible = true;
4843

49-
if (WScript.Arguments.Length > 0) {
50-
var path = WScript.Arguments(0);
51-
excel.Workbooks.Open(path);
52-
}
44+
var path = WScript.Arguments(0);
5345

5446
// for test, open a workbook
5547
// excel.Workbooks.Open('d:\\src\\excelview\\test.xlsx');
5648

5749
for (;;) {
5850
try {
59-
saveActiveRow(excel);
51+
saveActiveRow(excel, path);
6052
} catch (e) {
6153
WScript.Echo(e.message);
6254
}
6355

6456
WScript.Sleep(1000);
65-
}
57+
}

frontend/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
55
<script src="https://cdn.datatables.net/2.0.8/js/dataTables.js"></script>
66
<link href="https://cdn.datatables.net/2.0.8/css/dataTables.dataTables.css" rel="stylesheet">
7+
<!--SCRIPT-START-->
78
<script src="./ui.ts" type="module"></script>
9+
<!--SCRIPT-END-->
810
</head>
911
<body style="padding:10px;">
1012
</body>

static_assets.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"/index.html": "<html>\r\n <head>\r\n <title>Excel Navigate Helper</title>\r\n <link href=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH\" crossorigin=\"anonymous\">\r\n <script src=\"https://cdn.datatables.net/2.0.8/js/dataTables.js\"></script>\r\n <link href=\"https://cdn.datatables.net/2.0.8/css/dataTables.dataTables.css\" rel=\"stylesheet\">\r\n \r\n <script type=\"module\"> (function(){const s=document.createElement(\"link\").relList;if(s&&s.supports&&s.supports(\"modulepreload\"))return;for(const e of document.querySelectorAll('link[rel=\"modulepreload\"]'))c(e);new MutationObserver(e=>{for(const t of e)if(t.type===\"childList\")for(const a of t.addedNodes)a.tagName===\"LINK\"&&a.rel===\"modulepreload\"&&c(a)}).observe(document,{childList:!0,subtree:!0});function o(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===\"use-credentials\"?t.credentials=\"include\":e.crossOrigin===\"anonymous\"?t.credentials=\"omit\":t.credentials=\"same-origin\",t}function c(e){if(e.ep)return;e.ep=!0;const t=o(e);fetch(e.href,t)}})();const f={checkResult:async function(n,s,o){return await i(\"checkResult\",arguments)},getWindows:async function(){return await i(\"getWindows\",arguments)},launchExcel:async function(){return await i(\"launchExcel\",arguments)},getActiveExcelRow:async function(){return await i(\"getActiveExcelRow\",arguments)},closeBackend:async function(){return await i(\"closeBackend\",arguments)}};async function i(n,...s){const o=window.location.protocol,c=window.location.hostname;return await(await fetch(`${o}//${c}:8080/api?cmd=${n}&args=${encodeURIComponent(JSON.stringify(s))}`)).json()}let p=null,m=null,h={},g=!0;function w(n,s){h={},s.split(`\n`).forEach(o=>{const c=o.split(\":\");c.length>=2&&(h[c[0].trim()]=c.slice(1).join(\":\").trim())})}async function y(n,s=!1){const o=await f.getActiveExcelRow();if(!s&&m&&JSON.stringify(m)===JSON.stringify(o))return;m=o,p&&p.remove();const c=document.createElement(\"table\");c.classList.add(\"table\",\"table-bordered\"),n.appendChild(c);const e=document.createElement(\"tbody\");c.appendChild(e);for(let t=0;t<o.data.length;t++){const a=document.createElement(\"tr\");e.appendChild(a);const l=document.createElement(\"td\");l.style.fontWeight=\"bold\",a.appendChild(l),l.textContent=o.headings[t]||\"\",g||(l.style.display=\"none\");const r=document.createElement(\"td\");a.appendChild(r);const x=h[o.headings[t]];r.style.cssText=x||\"\";const d=o.data[t];if(d.startsWith(\"http\")){const u=document.createElement(\"a\");u.href=d,u.textContent=d,r.appendChild(u)}else r.textContent=o.data[t]}p=c}async function b(){const n=document.createElement(\"div\");document.body.appendChild(n);const s=document.createElement(\"div\");s.classList.add(\"alert\",\"alert-info\"),s.innerText=`This app keep sync with Excel and show the data in current(active) row so that you can see all columns without scrolling if there are too many columns.\nIt assume there is a heading row in Excel and use the heading as the first column in the table. `,n.appendChild(s);const o=document.createElement(\"button\");o.classList.add(\"btn\",\"btn-primary\"),o.style.marginRight=\"10px\",o.textContent=\"Launch Excel to open file\",o.onclick=async()=>{await f.launchExcel()},n.append(o);const c=document.createElement(\"button\");c.classList.add(\"btn\",\"btn-secondary\"),c.style.marginRight=\"10px\",c.textContent=\"Edit Style\",n.append(c),c.onclick=()=>{const l=document.getElementById(\"styleText\");l&&(l.style.display=l.style.display===\"none\"?\"block\":\"none\")};const e=document.createElement(\"button\");e.classList.add(\"btn\",\"btn-secondary\"),e.style.marginRight=\"10px\",e.textContent=\"Toggle Heading\",n.append(e),e.onclick=()=>{g=!g,y(n,!0)};const t=document.createElement(\"button\");t.classList.add(\"btn\",\"btn-danger\"),t.textContent=\"Close\",t.onclick=async()=>{await f.closeBackend(),window.close()},n.append(t);const a=document.createElement(\"textarea\");a.classList.add(\"form-control\"),a.id=\"styleText\",a.style.width=\"100%\",a.style.height=\"200px\",a.style.display=\"none\",a.style.marginTop=\"10px\",a.style.fontFamily=\"monospace\",a.value=localStorage.getItem(\"styleText\")||\"\",n.appendChild(a),a.onkeydown=()=>{const l=a.value;w(n,l),y(n,!0),localStorage.setItem(\"styleText\",l)},w(n,a.value),n.appendChild(document.createElement(\"p\")),setInterval(y,1e3,n)}document.addEventListener(\"DOMContentLoaded\",function(){b()},!1);\n </script>\n </head>\r\n <body style=\"padding:10px;\">\r\n </body>\r\n</html>\r\n",
3+
"/index2.html": "<html>\r\n <head>\r\n <title>Excel Navigate Helper</title>\r\n <link href=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH\" crossorigin=\"anonymous\">\r\n <script src=\"https://cdn.datatables.net/2.0.8/js/dataTables.js\"></script>\r\n <link href=\"https://cdn.datatables.net/2.0.8/css/dataTables.dataTables.css\" rel=\"stylesheet\">\r\n \r\n <script type=\"module\"> (function(){const s=document.createElement(\"link\").relList;if(s&&s.supports&&s.supports(\"modulepreload\"))return;for(const e of document.querySelectorAll('link[rel=\"modulepreload\"]'))c(e);new MutationObserver(e=>{for(const t of e)if(t.type===\"childList\")for(const a of t.addedNodes)a.tagName===\"LINK\"&&a.rel===\"modulepreload\"&&c(a)}).observe(document,{childList:!0,subtree:!0});function o(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===\"use-credentials\"?t.credentials=\"include\":e.crossOrigin===\"anonymous\"?t.credentials=\"omit\":t.credentials=\"same-origin\",t}function c(e){if(e.ep)return;e.ep=!0;const t=o(e);fetch(e.href,t)}})();const f={checkResult:async function(n,s,o){return await i(\"checkResult\",arguments)},getWindows:async function(){return await i(\"getWindows\",arguments)},launchExcel:async function(){return await i(\"launchExcel\",arguments)},getActiveExcelRow:async function(){return await i(\"getActiveExcelRow\",arguments)},closeBackend:async function(){return await i(\"closeBackend\",arguments)}};async function i(n,...s){const o=window.location.protocol,c=window.location.hostname;return await(await fetch(`${o}//${c}:8080/api?cmd=${n}&args=${encodeURIComponent(JSON.stringify(s))}`)).json()}let p=null,m=null,h={},g=!0;function w(n,s){h={},s.split(`\n`).forEach(o=>{const c=o.split(\":\");c.length>=2&&(h[c[0].trim()]=c.slice(1).join(\":\").trim())})}async function y(n,s=!1){const o=await f.getActiveExcelRow();if(!s&&m&&JSON.stringify(m)===JSON.stringify(o))return;m=o,p&&p.remove();const c=document.createElement(\"table\");c.classList.add(\"table\",\"table-bordered\"),n.appendChild(c);const e=document.createElement(\"tbody\");c.appendChild(e);for(let t=0;t<o.data.length;t++){const a=document.createElement(\"tr\");e.appendChild(a);const l=document.createElement(\"td\");l.style.fontWeight=\"bold\",a.appendChild(l),l.textContent=o.headings[t]||\"\",g||(l.style.display=\"none\");const r=document.createElement(\"td\");a.appendChild(r);const x=h[o.headings[t]];r.style.cssText=x||\"\";const d=o.data[t];if(d.startsWith(\"http\")){const u=document.createElement(\"a\");u.href=d,u.textContent=d,r.appendChild(u)}else r.textContent=o.data[t]}p=c}async function b(){const n=document.createElement(\"div\");document.body.appendChild(n);const s=document.createElement(\"div\");s.classList.add(\"alert\",\"alert-info\"),s.innerText=`This app keep sync with Excel and show the data in current(active) row so that you can see all columns without scrolling if there are too many columns.\nIt assume there is a heading row in Excel and use the heading as the first column in the table. `,n.appendChild(s);const o=document.createElement(\"button\");o.classList.add(\"btn\",\"btn-primary\"),o.style.marginRight=\"10px\",o.textContent=\"Launch Excel to open file\",o.onclick=async()=>{await f.launchExcel()},n.append(o);const c=document.createElement(\"button\");c.classList.add(\"btn\",\"btn-secondary\"),c.style.marginRight=\"10px\",c.textContent=\"Edit Style\",n.append(c),c.onclick=()=>{const l=document.getElementById(\"styleText\");l&&(l.style.display=l.style.display===\"none\"?\"block\":\"none\")};const e=document.createElement(\"button\");e.classList.add(\"btn\",\"btn-secondary\"),e.style.marginRight=\"10px\",e.textContent=\"Toggle Heading\",n.append(e),e.onclick=()=>{g=!g,y(n,!0)};const t=document.createElement(\"button\");t.classList.add(\"btn\",\"btn-danger\"),t.textContent=\"Close\",t.onclick=async()=>{await f.closeBackend(),window.close()},n.append(t);const a=document.createElement(\"textarea\");a.classList.add(\"form-control\"),a.id=\"styleText\",a.style.width=\"100%\",a.style.height=\"200px\",a.style.display=\"none\",a.style.marginTop=\"10px\",a.style.fontFamily=\"monospace\",a.value=localStorage.getItem(\"styleText\")||\"\",n.appendChild(a),a.onkeydown=()=>{const l=a.value;w(n,l),y(n,!0),localStorage.setItem(\"styleText\",l)},w(n,a.value),n.appendChild(document.createElement(\"p\")),setInterval(y,1e3,n)}document.addEventListener(\"DOMContentLoaded\",function(){b()},!1);\n </script>\n </head>\r\n <body style=\"padding:10px;\">\r\n </body>\r\n</html>\r\n",
4+
"excel.js": "// deno-lint-ignore-file no-var no-inner-declarations\r\n\r\nfunction WriteTextFile (text, path, encoding) {\r\n var stream = new ActiveXObject('ADODB.Stream');\r\n stream.Type = 2;\r\n stream.Mode = 3;\r\n if (encoding) stream.Charset = encoding;\r\n stream.Open();\r\n stream.Position = 0;\r\n stream.WriteText(text);\r\n stream.SaveToFile(path, 2);\r\n stream.Close();\r\n}\r\n\r\nfunction saveActiveRow(excel, path) {\r\n var sheet = excel.ActiveSheet;\r\n if (sheet) {\r\n // get max column that have data\r\n var maxColumn = sheet.UsedRange.Columns.Count;\r\n // get active range\r\n var cell = excel.ActiveCell;\r\n if (cell) {\r\n var activeRow = cell.Row;\r\n var rowValues = []\r\n var headings = []\r\n for (var i = 1; i <= maxColumn; i++) {\r\n var value = sheet.Cells(activeRow, i).Value;\r\n rowValues.push(value);\r\n var heading = sheet.Cells(1, i).Value;\r\n headings.push(heading);\r\n }\r\n var headings = headings.join('_@@HS@@_');\r\n var rowValues = rowValues.join('_@@VS@@_');\r\n var content = [headings, rowValues].join('_@@RS@@_');\r\n WScript.Echo(content);\r\n WriteTextFile(content, path, 'utf-8');\r\n }\r\n }\r\n}\r\n\r\nvar excel = new ActiveXObject('Excel.Application');\r\nexcel.Visible = true;\r\n\r\nvar path = WScript.Arguments(0);\r\n\r\n// for test, open a workbook\r\n// excel.Workbooks.Open('d:\\\\src\\\\excelview\\\\test.xlsx');\r\n\r\nfor (;;) {\r\n try {\r\n saveActiveRow(excel, path);\r\n } catch (e) {\r\n WScript.Echo(e.message);\r\n }\r\n\r\n WScript.Sleep(1000);\r\n}\r\n"
5+
}

vite.config.js

+9
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@
22
export default {
33
// ...
44
root: 'frontend',
5+
build: {
6+
rollupOptions: {
7+
output: {
8+
entryFileNames: `assets/[name].js`,
9+
chunkFileNames: `assets/[name].js`,
10+
assetFileNames: `assets/[name].[ext]`
11+
}
12+
}
13+
}
514
}

0 commit comments

Comments
 (0)