Web表格导出助手

从网页中提取表格并导出为Excel

  1. // ==UserScript==
  2. // @name Web表格导出助手
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.31
  5. // @description 从网页中提取表格并导出为Excel
  6. // @match *://*/*
  7. // @grant none
  8. // @license All Rights Reserved
  9. // @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.5/xlsx.full.min.js
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // 创建菜单按钮
  16. function createMenuButton() {
  17. const button = document.createElement('div');
  18. button.innerHTML = '📊';
  19. button.style.cssText = `
  20. position: fixed;
  21. top: 20px;
  22. left: 20px;
  23. background-color: #4CAF50;
  24. color: white;
  25. padding: 1px 2px;
  26. border-radius: 5px;
  27. cursor: pointer;
  28. z-index: 9999;
  29. box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  30. `;
  31. button.onclick = extractTables;
  32. document.body.appendChild(button);
  33. }
  34.  
  35. // 生成随机文件名
  36. function generateRandomFileName() {
  37. const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  38. const randomString = Array.from(
  39. {length: 6},
  40. () => chars[Math.floor(Math.random() * chars.length)]
  41. ).join('');
  42. const date = new Date();
  43. const dateStr = `${(date.getMonth() + 1).toString().padStart(2, '0')}${date.getDate().toString().padStart(2, '0')}`;
  44. return `${document.title || randomString}_${dateStr}`;
  45. }
  46.  
  47. // 导出Excel
  48. function exportToExcel(tables, index = null) {
  49. if (index !== null) {
  50. // 导出特定表格
  51. const table = tables[index];
  52. const wb = XLSX.utils.book_new();
  53. const ws = XLSX.utils.aoa_to_sheet(table);
  54. XLSX.utils.book_append_sheet(wb, ws, `Table ${index + 1}`);
  55.  
  56. const fileName = `${generateRandomFileName()}_table${index + 1}.xlsx`;
  57. XLSX.writeFile(wb, fileName);
  58. } else {
  59. // 导出所有表格
  60. tables.forEach((table, idx) => {
  61. const wb = XLSX.utils.book_new();
  62. const ws = XLSX.utils.aoa_to_sheet(table);
  63. XLSX.utils.book_append_sheet(wb, ws, `Table ${idx + 1}`);
  64.  
  65. const fileName = `${generateRandomFileName()}_table${idx + 1}.xlsx`;
  66. XLSX.writeFile(wb, fileName);
  67. });
  68. }
  69. }
  70.  
  71. // 提取表格数据
  72. function extractTables() {
  73. const tables = Array.from(document.querySelectorAll('table')).map(table => {
  74. // 提取表格数据
  75. return Array.from(table.rows).map(row =>
  76. Array.from(row.cells).map(cell => cell.innerText.trim())
  77. );
  78. });
  79.  
  80. if (tables.length === 0) {
  81. alert('未找到任何表格');
  82. return;
  83. }
  84.  
  85. // 创建对话框
  86. const previewHtml = tables.map((table, index) => `
  87. <div id="tablePreview${index}" style="
  88. margin-bottom: 15px;
  89. background-color: #f9f9f9;
  90. border-radius: 10px;
  91. overflow: hidden;
  92. box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  93. transition: transform 0.3s, box-shadow 0.3s;
  94. ">
  95. <div style="
  96. background-color: #2196F3;
  97. color: white;
  98. padding: 10px 15px;
  99. display: flex;
  100. align-items: center;
  101. justify-content: space-between;
  102. ">
  103. <h5 style="margin: 0;">表格 ${index + 1}</h5>
  104. <button onclick="document.dispatchEvent(new CustomEvent('exportSpecificTable', {detail: ${index}}))"
  105. style="
  106. background-color: white;
  107. color: #2196F3;
  108. border: none;
  109. padding: 5px 10px;
  110. border-radius: 5px;
  111. cursor: pointer;
  112. transition: background-color 0.3s;
  113. "
  114. onmouseover="this.style.backgroundColor='#f0f0f0'"
  115. onmouseout="this.style.backgroundColor='white'"
  116. >
  117. 导出
  118. </button>
  119. </div>
  120. <div style="
  121. max-height: 200px;
  122. overflow-y: auto;
  123. padding: 10px;
  124. ">
  125. <table style="
  126. width: 100%;
  127. border-collapse: collapse;
  128. ">
  129. ${table.slice(0, 5).map(row => `
  130. <tr style="border-bottom: 1px solid #e0e0e0;">
  131. ${row.map(cell => `
  132. <td style="
  133. padding: 8px;
  134. text-align: left;
  135. max-width: 150px;
  136. overflow: hidden;
  137. text-overflow: ellipsis;
  138. white-space: nowrap;
  139. ">${cell}</td>
  140. `).join('')}
  141. </tr>
  142. `).join('')}
  143. </table>
  144. </div>
  145. </div>
  146. `).join('');
  147.  
  148. const dialogHtml = `
  149. <div id="tableExportDialog" style="
  150. position: fixed;
  151. top: 50%;
  152. left: 50%;
  153. transform: translate(-50%, -50%);
  154. background: white;
  155. border-radius: 15px;
  156. box-shadow: 0 15px 50px rgba(0,0,0,0.2);
  157. max-width: 600px;
  158. width: 95%;
  159. max-height: 100%;
  160. overflow: auto;
  161. z-index: 10001;
  162. padding: 20px;
  163. ">
  164. <div style="
  165. background: linear-gradient(135deg, #2196F3, #1565c0);
  166. color: white;
  167. padding: 15px;
  168. border-radius: 10px 10px 0 0;
  169. margin: -20px -20px 20px;
  170. text-align: center;
  171. ">
  172. <h3 style="margin: 0;">选择要导出的表格</h3>
  173. </div>
  174.  
  175. <div id="tablePreviewContainer">
  176. ${previewHtml}
  177. </div>
  178.  
  179. <div style="
  180. display: flex;
  181. justify-content: center;
  182. margin-top: 20px;
  183. gap: 15px;
  184. ">
  185. <button id="exportAllBtn" style="
  186. background-color: #4CAF50;
  187. color: white;
  188. border: none;
  189. padding: 10px 20px;
  190. border-radius: 8px;
  191. cursor: pointer;
  192. transition: background-color 0.3s;
  193. "
  194. onmouseover="this.style.backgroundColor='#45a049'"
  195. onmouseout="this.style.backgroundColor='#4CAF50'"
  196. >
  197. 导出所有表格
  198. </button>
  199. <button id="cancelBtn" style="
  200. background-color: #f44336;
  201. color: white;
  202. border: none;
  203. padding: 10px 20px;
  204. border-radius: 8px;
  205. cursor: pointer;
  206. transition: background-color 0.3s;
  207. "
  208. onmouseover="this.style.backgroundColor='#d32f2f'"
  209. onmouseout="this.style.backgroundColor='#f44336'"
  210. >
  211. 取消
  212. </button>
  213. </div>
  214. </div>
  215. <div id="tableExportOverlay" style="
  216. position: fixed;
  217. top: 0;
  218. left: 0;
  219. width: 100%;
  220. height: 100%;
  221. background: rgba(0,0,0,0.5);
  222. backdrop-filter: blur(5px);
  223. z-index: 10000;
  224. "></div>
  225. `;
  226.  
  227. // 创建对话框
  228. const tempDiv = document.createElement('div');
  229. tempDiv.innerHTML = dialogHtml;
  230. document.body.appendChild(tempDiv.firstElementChild);
  231. document.body.appendChild(tempDiv.lastElementChild);
  232.  
  233. // 添加悬停效果
  234. const previews = document.querySelectorAll('[id^="tablePreview"]');
  235. previews.forEach(preview => {
  236. preview.addEventListener('mouseenter', () => {
  237. preview.style.transform = 'scale(1.02)';
  238. preview.style.boxShadow = '0 6px 12px rgba(0,0,0,0.15)';
  239. });
  240. preview.addEventListener('mouseleave', () => {
  241. preview.style.transform = 'scale(1)';
  242. preview.style.boxShadow = '0 4px 6px rgba(0,0,0,0.1)';
  243. });
  244. });
  245.  
  246. // 添加事件监听
  247. document.getElementById('exportAllBtn').onclick = () => {
  248. exportToExcel(tables);
  249. closeDialog();
  250. };
  251.  
  252. document.getElementById('cancelBtn').onclick = closeDialog;
  253. document.getElementById('tableExportOverlay').onclick = closeDialog;
  254.  
  255. // 监听导出特定表格事件
  256. document.addEventListener('exportSpecificTable', (e) => {
  257. exportToExcel(tables, e.detail);
  258. closeDialog();
  259. });
  260. }
  261.  
  262. // 关闭对话框
  263. function closeDialog() {
  264. const dialog = document.getElementById('tableExportDialog');
  265. const overlay = document.getElementById('tableExportOverlay');
  266. if (dialog) dialog.remove();
  267. if (overlay) overlay.remove();
  268. }
  269.  
  270. // 初始化
  271. function init() {
  272. createMenuButton();
  273. }
  274.  
  275. // 等待页面加载完成
  276. if (document.readyState === 'loading') {
  277. document.addEventListener('DOMContentLoaded', init);
  278. } else {
  279. init();
  280. }
  281. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址