直接把整個試算表連結發給別人除了要載入很久且會出現一堆不需要的按鍵,整個畫面很醜很沒有質感。而且如果你把其他隱私的資料也放在裡面,都會被一次看光光。那我們就來幫試算表包個糖衣吧

當你要分享表格給其他人看時,使用 Google 試算表把連結貼給別人是一個簡單快速的方法。除了可以套各種公式,修改資料會馬上同步,也可以開設權限讓其他人一起編輯。

罷特如果只是要給別人看資料比如說客戶名單、訂單資訊、直接把整個試算表連結發給別人除了要載入很久且會出現一堆不需要的按鍵,整個畫面很醜很沒有質感。而且如果你把其他隱私的資料也放在裡面,都會被一次看光光。

試算表 不難看但沒什麼質感
試算表 不難看但沒什麼質感

怎麼辦?幫它抹上一層糖衣!

我們來做一個超簡單的小網頁讓它自己去表格抓你要的資料來顯示。我們會寫一些程式 (HTML,CSS,Js)不過如果你不會也沒關系 w 只要跟著步驟複製貼上就可以了。今天我要來幫我的畫家朋友薩波來做一個網站讓他的委託人可以查看他畫圖的進度,還要讓電腦排序讓已經完成的委託排在下面。

薩波委託進度

開發者:毛哥EM(我) 類型:網站 網址:毛哥EM的基地

架一個網站!

你可以使用任何一個可以給你存放網站代碼的地方,比如說Github

我從Codepen上找到了一個很好看的表格模板來做修改。它在螢幕尺寸太窄的時候會用不同的版面來顯示,保持使用者體驗。你也可以找其他的模板或者是自己建立一個。

See the Pen Responsive Tables using LI by Faiz Ahmed (@faaezahmd) on CodePen.

我在網站上增加了一點文字、顏色 (CSS)、超連結 (<a>)、還有圖片、縮圖。以及簡單的出場動畫 (animate.css)來炫技

1<!doctype html>
2<head>
3        
4    <meta charset="utf-8" />
5    
6        
7    <title>薩波進度查詢表</title>
8        
9    <meta name="viewport" content="width=device-width, initial-scale=1" />
10    
11        
12    <link
13        href="https://Edit-Mr.github.io/code/sabooo/thumbnail.png"
14        rel="icon"
15        type="image/x-icon"
16    />
17        
18    <link
19        rel="stylesheet"
20        type="text/css"
21        href="https://Edit-Mr.github.io/css/Animate.css"
22        media="screen"
23    />
24    
25        
26    <meta name="theme-color" content="orange" />
27        
28    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
29    
30        
31    <style>
32                @import url(https://fonts.googleapis.com/earlyaccess/cwtexyen.css);
33
34                body {
35                    font-family"Arial","cwTeXYen","微軟正黑體";
36                    background-color#fee5bd;
37                }
38
39                .container {
40                    max-width1000px;
41                    margin-left: auto;
42                    margin-right: auto;
43                    padding-left10px;
44                    padding-right10px;
45                    font-size25px;
46                }
47
48                h2 {
49                    font-size23px;
50                    margin0;
51                    text-align: center;
52                    font-weight150;
53                    color#e69137;
54                    animation: fadeIn;
55                    animation-duration1.5s;
56                    animate-delay: 0.9s;
57                }
58
59                h1 {
60                    font-size35px;
61                    margin20px 0 0 0;
62                    text-align: center;
63                    size: 30px;
64                    color#351c75;
65                    animation: zoomIn;
66                    animation-duration1s;
67                }
68
69                li {
70                    border-radius3px;
71                    padding25px 30px;
72                    display: flex;
73                    justify-content: space-between;
74                    margin-bottom25px;
75                }
76
77                .responsive-table .table-header,
78                .table-note {
79                    background-color#f9a756;
80                    font-size30px;
81                    margin-top0px;
82                    padding25px 30px 25px 30px;
83                    animation: slideInUp;
84                    animation-duration1.5s;
85                }
86
87                .table-note {
88                    font-size20px;
89                    display: none;
90                }
91
92                .responsive-table {
93                    margin0;
94                    padding0;
95                }
96
97                .responsive-table .table-row {
98                    background-color#fff;
99                    box-shadow0px 0px 9px 0px rgba(0000.1);
100                    animation: backInLeft;
101                    animation-duration1.5s;
102                }
103                .table-row{}
104                .responsive-table .col-1 {
105                    flex-basis25%;
106                }
107
108                .responsive-table .col-2 {
109                    flex-basis30%;
110                }
111
112                .responsive-table .col-3 {
113                    flex-basis30%;
114                }
115
116                .responsive-table .col-4 {
117                    flex-basis15%;
118                }
119
120                @media all and (max-width767px) {
121                    .responsive-table .table-header {
122                        display: none;
123                    }
124
125                    .table-note {
126                        display: block;
127                    }
128
129                    .responsive-table li {
130                        display: block;
131                    }
132
133                    .responsive-table .col {
134                        flex-basis100%;
135                    }
136
137                    .responsive-table .col {
138                        display: flex;
139                        padding10px 0;
140                    }
141
142                    .responsive-table .col:before {
143                        color#6c7a89;
144                        padding-right10px;
145                        contentattr(data-label);
146                        flex-basis50%;
147                        text-align: right;
148                    }
149                }
150
151                .header {
152                    width150px;
153                    display: block;
154                    margin: auto;
155                    animation: slideInUp;
156                    animation-duration1.5s;
157                }
158
159                .finished {
160                    color: green;
161                }
162
163                p,
164                a {
165                    text-align: center;
166                    font-size15px;
167                    color#6c7a89;
168                    text-decoration: none;
169                    animation: fadeIn;
170                    animation-duration1.5s;
171                }
172            
173    </style>
174</head>
175
176<body>
177        
178    <div class="container">
179                
180        <h1>薩波 2022 委託與贈圖表</h1>
181                
182        <h2>這些不代表畫的順序 會跳著畫</h2>
183                <img src="header.png" class="header" />         
184        <li class="table-note">
185                        如果要一次看完整表格請切換到電腦版網頁喔         
186        </li>
187                
188        <ul class="responsive-table">
189                        
190            <li class="table-header">
191                                
192                <div class="col col-1">委託人姓名</div>
193                                
194                <div class="col col-2">委託項目</div>
195                                
196                <div class="col col-3">付款狀態</div>
197                                
198                <div class="col col-4">進度狀態</div>
199                            
200            </li>
201                        資料載入中         
202        </ul>
203        <p>
204            <a href=""></a> · Facebook<a href="https://instagram.com/"
205                >Instagram</a
206            ><br />Made by <a href="https://github.com/Edit-Mr">Edit Mr.</a
207            > with❤
208        </p>
209            
210    </div>
211</body>

後端 GAS! GAS!

好了前端做好了接下來我們來建另一個網站讓剛才那個網站來這裡讀取資料。為了方便起見我們在給資料的時候直接給一個做好的表格讓網站貼上。

我們先看一下試算表。在這裡我們可以看到每一行資料有 5 項,其中我希望第 5 項的資料可以放在付款狀態後面。現在請你先請你複製這個試算表的 ID,也就是網址https://docs.google.com/spreadsheets/d//之間那一串 (如1fjX-prGu0hfb65LCQkrktWa-JavvjSz7tWMmYWAb7RA)。等一下會用到。

再看一次試算表
再看一次試算表

我們會使用 GAS(Google Apps Script) 來建立網頁應用程式來讀取表格資料。

Google Apps Script

開發者:Google 類型:免費網站(可付費升級) 網址:script.google.com

請建立一個新的專案並貼上以下內容。記得貼上 Google Sheet 那段 ID,並修改自己要的範圍,程式碼裡有詳細的註解。原理是讀取一行行的資料並轉成 HTML 表格,其中如果狀態是完成的加上一個 class 讓顏色變綠色。在排序方面我是把完成的和未完成的分成兩個陣列(清單)儲存,在把完成的接在未完成的後面合併。

小叮嚀 為避免程式碼站太多空間,可能會部分隱藏。請記得展開或直接複製。

1function doGet() {
2    var spreadsheet = SpreadsheetApp.openById(
3        "1U-Q2XXXXXXXRsrh-QYCXXXXXXXXXQmGQ"
4    ); // Sheet id
5    var sheet = spreadsheet.getSheets()[0];
6    var rowLength = sheet.getLastRow();
7    var columnLength = sheet.getLastColumn();
8    var data = sheet.getRange(3, 1, rowLength, columnLength).getValues();
9    var dataExport = [
10        '<li class="table-header"><div class="col col-1">委託人姓名</div><div class="col col-2"++>委託項目</div><div class="col col-3">付款狀態</div><div class="col col-4">進度狀態</div></li>'
11    ];
12    var stat,
13        ed = [];
14    // 一個個加入 json
15    for (i in data) {
16        if (data[i][0] != "") {
17            if (data[i][3] == "完成") {
18                ed.push(
19                    '<li class="table-row"><div class="col col-1" data-label="委託人姓名">' +
20                        data[i][0] +
21                        '</div><div class="col col-2" data-label="委託項目">' +
22                        data[i][1] +
23                        '</div><div class="col col-3" data-label="付款狀態">' +
24                        data[i][2] +
25                        " " +
26                        data[i][4] +
27                        '</div><div class="col col-4 finished" data-label="進度狀態">' +
28                        data[i][3] +
29                        "</div></li>"
30                );
31            } else {
32                dataExport.push(
33                    '<li class="table-row"><div class="col col-1" data-label="委託人姓名">' +
34                        data[i][0] +
35                        '</div><div class="col col-2" data-label="委託項目">' +
36                        data[i][1] +
37                        '</div><div class="col col-3" data-label="付款狀態">' +
38                        data[i][2] +
39                        " " +
40                        data[i][4] +
41                        '</div><div class="col col-4" data-label="進度狀態">' +
42                        data[i][3] +
43                        "</div></li>"
44                );
45            }
46        }
47    }
48    dataExport = dataExport.concat(ed);
49    // 回傳 JSON
50    console.log(dataExport.join(""));
51    return ContentService.createTextOutput(dataExport.join(""));
52}

為什麼要分兩個陣列?不要讓未完成的直接插入到最前面? 我們可以用push()將資料插入到最後面,也可以用unshift()插入到最前面。但是如果用這個方式未完成的清單順序會整個便相反 如順序1234567排序後不會變124589367,而是985421367

你可以根據自己的需求決定排法

GAS 快速教學
GAS 快速教學

做好了之後點擊執行▶️,你會需要授予你的程式讀取資料的權限。因為你寫的程式沒有被 Google 驗證過所以會顯示不安全,但我相信你不會把你的帳號搞爆,對吧

接下來我們要部署它,讓它成為一個網站來讓我們抓。這裡選擇網頁應用程式,所有人都以你的身份讀取。按下部署就可以囉

這裡我們把部署的網址複製起來。如果要做修改除了按儲存之外要記得重新部署成新版本才會更新喔

接下來我們回到 Github 的網頁讓他來讀這個表格

等等,不是做好表格網頁了,直接讓它顯示就好了啊幹嘛那麼麻煩? 可以當然是可以,姑且不論網址有多長多醜,如果使用 Google Apps Script 建設的網站會出現橫幅很醜的一個警告,而且他超長讓你的版面整個跑掉。為了更好的使用者體驗既然都做了就做到底吧!

前端 讀取資料

最後一步了!我們回到程式碼的 head 裡面,加入 jQuery 這個套件讓我們可以少寫幾行

然後我們修改一下body。程式讀到表格之後會用表格取代class裡面的所有內容。我已在這裡可以寫一些表格讀取到之前會顯示的訊息比如說「資料讀取中...」之類的。

最後在我們在</body>前面貼上以下的 JavaScript 來讀取並顯示表格。記得把網址換成剛剛表格資料的網址喔~

1<script>
2    //請把下面按這串改成剛才的網址
3    let requestURL =
4        "https://script.google.com/macros/s/AKfycbxq942U9fZK5tR6Vi1OZkr5Hq0Bv_qPSm1rOOYFFZUS_vyrTu60QuW7xmU-d09UpI1XLQ/exec";
5    let request = new XMLHttpRequest();
6    request.open("GET", requestURL);
7    request.responseType = "text";
8    request.send();
9    request.onload = function () {
10        console.log("載入成功");
11        $("p").addClass("animate_animated", "animate_fadeOut"); //動畫
12        $(".responsive-table").html(request.response); //用表格取代.responsive-table
13    };
14</script>

最終程式碼

最終的程式碼如下,有沒有超有成就感?

顯示網站

1<!doctype html>
2<head>
3        
4    <meta charset="utf-8" />
5    
6        
7    <title>薩波進度查詢表</title>
8        
9    <meta name="viewport" content="width=device-width, initial-scale=1" />
10    
11        
12    <link
13        href="https://Edit-Mr.github.io/code/sabooo/thumbnail.png"
14        rel="icon"
15        type="image/x-icon"
16    />
17        
18    <link
19        rel="stylesheet"
20        type="text/css"
21        href="https://Edit-Mr.github.io/css/Animate.css"
22        media="screen"
23    />
24    
25        
26    <meta name="theme-color" content="orange" />
27        
28    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
29    
30        
31    <style>
32                @import url(https://fonts.googleapis.com/earlyaccess/cwtexyen.css);
33
34                body {
35                    font-family"Arial","cwTeXYen","微軟正黑體";
36                    background-color#fee5bd;
37                }
38
39                .container {
40                    max-width1000px;
41                    margin-left: auto;
42                    margin-right: auto;
43                    padding-left10px;
44                    padding-right10px;
45                    font-size25px;
46                }
47
48                h2 {
49                    font-size23px;
50                    margin0;
51                    text-align: center;
52                    font-weight150;
53                    color#e69137;
54                    animation: fadeIn;
55                    animation-duration1.5s;
56                    animate-delay: 0.9s;
57                }
58
59                h1 {
60                    font-size35px;
61                    margin20px 0 0 0;
62                    text-align: center;
63                    size: 30px;
64                    color#351c75;
65                    animation: zoomIn;
66                    animation-duration1s;
67                }
68
69                li {
70                    border-radius3px;
71                    padding25px 30px;
72                    display: flex;
73                    justify-content: space-between;
74                    margin-bottom25px;
75                }
76
77                .responsive-table .table-header,
78                .table-note {
79                    background-color#f9a756;
80                    font-size30px;
81                    margin-top0px;
82                    padding25px 30px 25px 30px;
83                    animation: slideInUp;
84                    animation-duration1.5s;
85                }
86
87                .table-note {
88                    font-size20px;
89                    display: none;
90                }
91
92                .responsive-table {
93                    margin0;
94                    padding0;
95                }
96
97                .responsive-table .table-row {
98                    background-color#fff;
99                    box-shadow0px 0px 9px 0px rgba(0000.1);
100                    animation: backInLeft;
101                    animation-duration1.5s;
102                }
103                .table-row{}
104                .responsive-table .col-1 {
105                    flex-basis25%;
106                }
107
108                .responsive-table .col-2 {
109                    flex-basis30%;
110                }
111
112                .responsive-table .col-3 {
113                    flex-basis30%;
114                }
115
116                .responsive-table .col-4 {
117                    flex-basis15%;
118                }
119
120                @media all and (max-width767px) {
121                    .responsive-table .table-header {
122                        display: none;
123                    }
124
125                    .table-note {
126                        display: block;
127                    }
128
129                    .responsive-table li {
130                        display: block;
131                    }
132
133                    .responsive-table .col {
134                        flex-basis100%;
135                    }
136
137                    .responsive-table .col {
138                        display: flex;
139                        padding10px 0;
140                    }
141
142                    .responsive-table .col:before {
143                        color#6c7a89;
144                        padding-right10px;
145                        contentattr(data-label);
146                        flex-basis50%;
147                        text-align: right;
148                    }
149                }
150
151                .header {
152                    width150px;
153                    display: block;
154                    margin: auto;
155                    animation: slideInUp;
156                    animation-duration1.5s;
157                }
158
159                .finished {
160                    color: green;
161                }
162
163                p,
164                a {
165                    text-align: center;
166                    font-size15px;
167                    color#6c7a89;
168                    text-decoration: none;
169                    animation: fadeIn;
170                    animation-duration1.5s;
171                }
172            
173    </style>
174</head>
175
176<body>
177        
178    <div class="container">
179                
180        <h1>薩波 2022 委託與贈圖表</h1>
181                
182        <h2>這些不代表畫的順序 會跳著畫</h2>
183                <img src="header.png" class="header" />         
184        <li class="table-note">
185                        如果要一次看完整表格請切換到電腦版網頁喔         
186        </li>
187                
188        <ul class="responsive-table">
189                        
190            <li class="table-header">
191                                
192                <div class="col col-1">委託人姓名</div>
193                                
194                <div class="col col-2">委託項目</div>
195                                
196                <div class="col col-3">付款狀態</div>
197                                
198                <div class="col col-4">進度狀態</div>
199                            
200            </li>
201                        資料載入中         
202        </ul>
203                
204        <p>
205            <a href="https://www.facebook.com/Sabo9335">薩波 FB</a> · <a
206                href="https://instagram.com/sabooo_9335?igshid=YmMyMTA2M2Y="
207                >薩波 IG</a
208            > · <a href="https://discord.gg/ve9ERWVEPR">橘子牌太空船</a
209            ><br />Made by <a href="https://github.com/Edit-Mr">EDM</a> with❤
210        </p>
211            
212    </div>
213        
214    <script>
215        //請把下面按這串改成剛才的網址
216        let requestURL = "https://script.google.com/macros/s/xxxxxxxx/exec";
217        let request = new XMLHttpRequest();
218        request.open("GET", requestURL);
219        request.responseType = "text";
220        request.send();
221        request.onload = function () {
222            console.log("載入成功");
223            $("p").addClass("animate_animated", "animate_fadeOut"); //動畫
224            $(".responsive-table").html(request.response); //用表格取代.responsive-table
225        };
226    </script>
227</body>

表格資料網站

1function doGet() {
2    var spreadsheet = SpreadsheetApp.openById(
3        "1U-Q2t9RI6Uce787RASQIRsrh-QYCvhCgn_UyOnrQmGQ"
4    ); // Sheet id
5    var sheet = spreadsheet.getSheets()[0];
6    var rowLength = sheet.getLastRow();
7    var columnLength = sheet.getLastColumn();
8    var data = sheet.getRange(3, 1, rowLength, columnLength).getValues();
9    var dataExport = [
10        '<li class="table-header"><div class="col col-1">委託人姓名</div><div class="col col-2"++>委託項目</div><div class="col col-3">付款狀態</div><div class="col col-4">進度狀態</div></li>'
11    ];
12    var stat,
13        ed = [];
14    // 一個個加入 json
15    for (i in data) {
16        if (data[i][0] != "") {
17            if (data[i][3] == "完成") {
18                ed.push(
19                    '<li class="table-row"><div class="col col-1" data-label="委託人姓名">' +
20                        data[i][0] +
21                        '</div><div class="col col-2" data-label="委託項目">' +
22                        data[i][1] +
23                        '</div><div class="col col-3" data-label="付款狀態">' +
24                        data[i][2] +
25                        " " +
26                        data[i][4] +
27                        '</div><div class="col col-4 finished" data-label="進度狀態">' +
28                        data[i][3] +
29                        "</div></li>"
30                );
31            } else {
32                dataExport.push(
33                    '<li class="table-row"><div class="col col-1" data-label="委託人姓名">' +
34                        data[i][0] +
35                        '</div><div class="col col-2" data-label="委託項目">' +
36                        data[i][1] +
37                        '</div><div class="col col-3" data-label="付款狀態">' +
38                        data[i][2] +
39                        " " +
40                        data[i][4] +
41                        '</div><div class="col col-4" data-label="進度狀態">' +
42                        data[i][3] +
43                        "</div></li>"
44                );
45            }
46        }
47    }
48    dataExport = dataExport.concat(ed);
49    // 回傳 JSON
50    console.log(dataExport.join(""));
51    return ContentService.createTextOutput(dataExport.join(""));
52}

毛哥EM

一位喜歡把簡單的事,做得不簡單的高三生。