【GAS】複製貼上讓試算表變身成網頁表格 秀爆你的客戶朋友!

文章目錄

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

當你要分享表格給其他人看時,使用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     <meta charset="utf-8" /> 
  4     <!--下面這行是標題-->
  5     <title>薩波進度查詢表</title> 
  6     <meta name="viewport" content="width=device-width, initial-scale=1" /> 
  7     <!--下面這行是縮圖,可以換網址-->
  8     <link href="https://Edit-Mr.github.io/code/sabooo/thumbnail.png" rel="icon" type="image/x-icon"> 
  9     <link rel="stylesheet" type="text/css" href="https://Edit-Mr.github.io/css/Animate.css" media="screen"> 
 10     <!--下面這行是主題顏色,可以自由更換(支援HEX)-->
 11     <meta name="theme-color" content="orange" /> 
 12     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 13    <!--下面這些是樣式,可以自由更換顏色之類的-->
 14     <style> 
 15         @import url(https://fonts.googleapis.com/earlyaccess/cwtexyen.css); 
 16  
 17         body { 
 18             font-family: "Arial","cwTeXYen","微軟正黑體"; 
 19             background-color: #fee5bd; 
 20         } 
 21  
 22         .container { 
 23             max-width: 1000px; 
 24             margin-left: auto; 
 25             margin-right: auto; 
 26             padding-left: 10px; 
 27             padding-right: 10px; 
 28             font-size: 25px; 
 29         } 
 30  
 31         h2 { 
 32             font-size: 23px; 
 33             margin: 0; 
 34             text-align: center; 
 35             font-weight: 150; 
 36             color: #e69137; 
 37             animation: fadeIn; 
 38             animation-duration: 1.5s; 
 39             animate-delay: 0.9s; 
 40         } 
 41  
 42         h1 { 
 43             font-size: 35px; 
 44             margin: 20px 0 0 0; 
 45             text-align: center; 
 46             size: 30px; 
 47             color: #351c75; 
 48             animation: zoomIn; 
 49             animation-duration: 1s; 
 50         } 
 51  
 52         li { 
 53             border-radius: 3px; 
 54             padding: 25px 30px; 
 55             display: flex; 
 56             justify-content: space-between; 
 57             margin-bottom: 25px; 
 58         } 
 59  
 60         .responsive-table .table-header, 
 61         .table-note { 
 62             background-color: #f9a756; 
 63             font-size: 30px; 
 64             margin-top: 0px; 
 65             padding: 25px 30px 25px 30px; 
 66             animation: slideInUp; 
 67             animation-duration: 1.5s; 
 68         } 
 69  
 70         .table-note { 
 71             font-size: 20px; 
 72             display: none; 
 73         } 
 74  
 75         .responsive-table { 
 76             margin: 0; 
 77             padding: 0; 
 78         } 
 79  
 80         .responsive-table .table-row { 
 81             background-color: #fff; 
 82             box-shadow: 0px 0px 9px 0px rgba(0, 0, 0, 0.1); 
 83             animation: backInLeft; 
 84             animation-duration: 1.5s; 
 85         } 
 86         .table-row{} 
 87         .responsive-table .col-1 { 
 88             flex-basis: 25%; 
 89         } 
 90  
 91         .responsive-table .col-2 { 
 92             flex-basis: 30%; 
 93         } 
 94  
 95         .responsive-table .col-3 { 
 96             flex-basis: 30%; 
 97         } 
 98  
 99         .responsive-table .col-4 { 
100             flex-basis: 15%; 
101         } 
102  
103         @media all and (max-width: 767px) { 
104             .responsive-table .table-header { 
105                 display: none; 
106             } 
107  
108             .table-note { 
109                 display: block; 
110             } 
111  
112             .responsive-table li { 
113                 display: block; 
114             } 
115  
116             .responsive-table .col { 
117                 flex-basis: 100%; 
118             } 
119  
120             .responsive-table .col { 
121                 display: flex; 
122                 padding: 10px 0; 
123             } 
124  
125             .responsive-table .col:before { 
126                 color: #6c7a89; 
127                 padding-right: 10px; 
128                 content: attr(data-label); 
129                 flex-basis: 50%; 
130                 text-align: right; 
131             } 
132         } 
133  
134         .header { 
135             width: 150px; 
136             display: block; 
137             margin: auto; 
138             animation: slideInUp; 
139             animation-duration: 1.5s; 
140         } 
141  
142         .finished { 
143             color: green; 
144         } 
145  
146         p, 
147         a { 
148             text-align: center; 
149             font-size: 15px; 
150             color: #6c7a89; 
151             text-decoration: none; 
152             animation: fadeIn; 
153             animation-duration: 1.5s; 
154         } 
155     </style> 
156 </head> 
157  
158 <body> 
159     <div class="container"> 
160         <h1>薩波2022委託與贈圖表</h1> 
161         <h2>這些不代表畫的順序 會跳著畫</h2> 
162         <img src="header.png" class="header" /> 
163         <li class="table-note"> 
164             如果要一次看完整表格請切換到電腦版網頁喔 
165         </li> 
166         <ul class="responsive-table"> 
167             <li class="table-header"> 
168                 <div class="col col-1">委託人姓名</div> 
169                 <div class="col col-2">委託項目</div> 
170                 <div class="col col-3">付款狀態</div> 
171                 <div class="col col-4">進度狀態</div> 
172             </li> 
173             資料載入中 
174         </ul> 
175         <p><a href=""></a> · Facebook<a href="https://instagram.com/">Instagram</a><br />Made by <a href="https://github.com/Edit-Mr">Edit Mr.</a> with❤</p>
176     </div> 
177 </body>

後端 GAS! GAS!

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

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

再看一次試算表

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

Google App Script

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

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

小叮嚀
為避免程式碼站太多空間,可能會部分隱藏。請記得展開或直接複製。
 1function doGet(){
 2  var spreadsheet = SpreadsheetApp.openById('1U-Q2XXXXXXXRsrh-QYCXXXXXXXXXQmGQ'); // Sheet id
 3  var sheet = spreadsheet.getSheets()[0];
 4  var rowLength = sheet.getLastRow();
 5  var columnLength = sheet.getLastColumn();
 6  var data = sheet.getRange(3,1,rowLength,columnLength).getValues();
 7  var dataExport = ['<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>'];
 8  var stat, ed=[];
 9  // 一個個加入json
10  for(i in data){
11    if(data[i][0] != ""){
12      if (data[i][3]=="完成"){
13    ed.push('<li class="table-row"><div class="col col-1" data-label="委託人姓名">'+data[i][0]
14+'</div><div class="col col-2" data-label="委託項目">'+data[i][1]
15+'</div><div class="col col-3" data-label="付款狀態">'+data[i][2]+" "+data[i][4]
16+'</div><div class="col col-4 finished" data-label="進度狀態">'+data[i][3]+'</div></li>')
17      }else{
18    dataExport.push('<li class="table-row"><div class="col col-1" data-label="委託人姓名">'+data[i][0]
19+'</div><div class="col col-2" data-label="委託項目">'+data[i][1]
20+'</div><div class="col col-3" data-label="付款狀態">'+data[i][2]+" "+data[i][4]
21+'</div><div class="col col-4" data-label="進度狀態">'+data[i][3]+'</div></li>')
22      }
23
24    };
25  };
26  dataExport=dataExport.concat(ed);
27  // 回傳JSON
28  console.log(dataExport.join(""));
29  return ContentService.createTextOutput(dataExport.join(""));
30  }
為什麼要分兩個陣列?不要讓未完成的直接插入到最前面?

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

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

GAS快速教學

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

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

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

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

等等,不是做好表格網頁了,直接讓它顯示就好了啊幹嘛那麼麻煩?

可以當然是可以,姑且不論網址有多長多醜,如果使用Google App Script建設的網站會出現橫幅很醜的一個警告,而且他超長讓你的版面整個跑掉。為了更好的使用者體驗既然都做了就做到底吧!

前端 讀取資料

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

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

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

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

最終程式碼

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

顯示網站

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

表格資料網站

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

Posts in this Series