如何从 Google 表格创建 Markdown 表格?
此代码允许您从电子表格中复制数据,对其进行编辑,独立对齐每一列,然后使用适当的降价将其发布到 SO 中,以制作一个漂亮的表格。
代码:
redact.gs:
function onOpen() {
menu();
}
function menu() {
SpreadsheetApp.getUi().createMenu('My Tools')
.addItem('Authenticate','authenticate')
.addItem('Redactable Table','showRedactTableDialog')
.addToUi();
}
function authenticate() {
//no nothing
}
function getCSVDataRange() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const rg=sh.getActiveRange();
const cols=rg.getWidth();
const datarange=rg.getA1Notation();
return {datarange:datarange,columns:cols};
}
function getRedactRangeList() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const rgA=sh.getActiveRangeList().getRanges();
const redactrange=rgA.map(function(rg,i){return rg.getA1Notation();}).join(',');
return {redactrange:redactrange};
}
function showRedactTableDialog() {
var userInterface=HtmlService.createHtmlOutputFromFile('redacttable').setWidth(400).setHeight(200);
const h=userInterface.getHeight();
const w=userInterface.getWidth();
const title='Redactable Data Table';
userInterface.append(Utilities.formatString('<div id="dim">w:%s,h:%s</div>',w,h));
SpreadsheetApp.getUi().showModelessDialog(userInterface, title);
}
function getPresets() {
return {datarange:'',redactrange:'',delimiter:',',redactstring:'Redacted'};
}
function getTablePresets() {
return {datarange:'',redactrange:'',align:'c',redactstring:'Redacted',aligntext:""};
}
function testrdtable() {
redactableDataTable({"redactrange":"","cols":"3","col":"3","align":"l","aligntext":"rrr","datarange":"A1:C4","redactstring":"Redacted"})
}
function redactableDataTable(obj) {
Logger.log(JSON.stringify(obj));
const {datarange,redactrange,redactstring,align,aligntext}=obj;
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const drg=sh.getRange(datarange);
const vA=drg.getValues();
//new parameters
const dlm='|';
const dlmrow={l:':---',c:':---:',r:'---:'};
const aline=(aligntext.length>0)?aligntext:align;
if(redactrange) {
const rgA1=redactrange.split(',');
//Logger.log(rgA1);
const rgA=rgA1.map(function(A1,i){
return sh.getRange(A1);
});
const rowStart=drg.getRow();
const colStart=drg.getColumn();
//const rowEnd=drg.getRow()+drg.getHeight()-1;
//const colEnd=drg.getColumn()+drg.getWidth()-1;
rgA.forEach(function(rg,k){
var v=rg.getDisplayValues();
let row=rg.getRow();
let col=rg.getColumn();
v.forEach(function(r,i){
r.forEach(function(c,j){
vA[row-rowStart+i][col-colStart+j]=redactstring;//redact string
});
});
});
}
var tsv='';
var hdr=[vA.shift()];
//header row
hdr.forEach(function(r,i){tsv+=dlm;r.forEach(function(c,j){if(j>0)tsv+=dlm;tsv+=c;});tsv+=dlm;});
tsv+='\r\n';
//delimiter row
hdr.forEach(function(r,i){tsv+=dlm;r.forEach(function(c,j){if(j>0)tsv+=dlm;tsv+=dlmrow[aline[j%aline.length]];});tsv+=dlm;});
tsv+='\r\n';
//data table
vA.forEach(function(r,i){if(i>0){tsv+='\r\n';}tsv+=dlm;r.forEach(function(c,j){if(j>0){tsv+=dlm;}tsv+=c;});tsv+=dlm;});
let s=`Data:${datarange} - Redact:${redactrange}`;
var html=Utilities.formatString('<body><input type="button" value="Exit" onClick="google.script.host.close();" /><br /><textarea rows="1" cols="150" id="rngs">%s</textarea><br /><textarea rows="30" cols="150" id="tsv">%s</textarea></body>',s,tsv);
html+='<br /><input type="button" value="Exit" onClick="google.script.host.close();" />';
console.log(html);
var ui=HtmlService.createHtmlOutput(html).setWidth(1200);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Table Markdown');
}
html代码:
redacttable.hmtl:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
select,
input {
margin: 2px 5px 2px 0;
font-size: 12px;
}
#cols {
margin: 2px 5px 2px 5px;
font-size: 12px;
}
.bold {
font-weight: "bold";
}
</style>
</head>
<body>
<form name="form">
<br /><input type="text" id="dtrg" name="datarange" placeholder="Select Data Range" size="20" readonly /><input type="button" value="Data" onClick="getDataRange();" title="Select Data Range." /><input type="text" id="cols" name="cols" size="2" readonly />Cols
<br /><input type="text" id="rdrg" name="redactrange" placeholder="Select Redact Ranges" size="20" readonly /><input type="button" value="Redact" onClick="getRedactRangelist();" title="Select Redact Rangelist." />
<br /><span class="bold">Alignment</span>
<br /><select name="align"><option value="l">left</option><option value="c">center</option><option value="r">right</option></select>
<input type="text" id="alntxt" name="aligntext" placeholder="Align all columns with r,c,or l only" size="25" oninput="getLength();" /><input type="text" name="col" id="col" size="2" readonly />
<br /><input type="text" id="rs" name="redactstring" size="15" />Redact String
<br /><input type="button" value="Submit" onClick="processForm(this.parentNode);" />
</form>
<script>
$(function(){
google.script.run
.withSuccessHandler(function(obj){
if(obj.datarange) {$('#dtrg').val(obj.datarange);}
if(obj.redactrange) {$('#rdrg').val(obj.redactrange);}
if(obj.align) {$('#aln').val(obj.align);}
if(obj.redactstring) {$('#rs').val(obj.redactstring);}
if(obj.aligntext){$('$alntxt').val(obj.aligntext);}
})
.getTablePresets();
});
function getLength() {
let s=$('#alntxt').val();
let all='rlc';
if(!all.includes(s[s.length-1])){
$('#alntxt').val(s.slice(0,-1));
}
$('#col').val($('#alntxt').val().length);
}
function getDataRange() {
google.script.run
.withSuccessHandler(function(obj){
$('#dtrg').val(obj.datarange);
$('#cols').val(obj.columns);
})
.getCSVDataRange();
}
function getRedactRangelist() {
google.script.run
.withSuccessHandler(function(obj){
$('#rdrg').val(obj.redactrange);
})
.getRedactRangeList();
}
function processForm(form) {
google.script.run.redactableDataTable(form);
}
console.log('My Code');
</script>
</body>
</html>
tableMarkdown.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>';
</head>
<body>
<input type="button" value="Exit" onClick="google.script.host.close();" /><br />
<textarea rows="1" cols="150" id="rngs"></textarea><br /><textarea rows="30" cols="150" id="tsv"></textarea>
<br /><input type="button" value="Exit" onClick="google.script.host.close();" />
<script>
$(function(){
google.script.run
.withSuccessHandler((robj)=>{
$("#tsv").val(robj.tsv);
$("#rngs").val(robj.rngs);
}).redactableDataTable(obj);
});
</script>
</body>
</html>
此脚本也可在此处获取:https://sites.google.com/view/googlappsscript/table-utility
演示:
此版本会自动生成列字母和行号,我发现这在数据中没有标题的情况下很有用,因为它有助于提供一个框架来理解表格的位置。 无论如何都玩它。 不难弄清楚。
GS:
function showRedactTableDialog() {
var userInterface = HtmlService.createHtmlOutputFromFile('redacttable').setWidth(400).setHeight(250);
const h = userInterface.getHeight();
const w = userInterface.getWidth();
const title = 'Redactable Data Table';
userInterface.append(Utilities.formatString('<div id="dim">w:%s,h:%s</div>', w, h));
SpreadsheetApp.getUi().showModelessDialog(userInterface, title);
}
function redactableDataTable(obj) {
Logger.log(JSON.stringify(obj));
const { datarange, redactrange, headers, rows, redactstring, align, aligntext } = obj;
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const drg = sh.getRange(datarange);
const vA = drg.getDisplayValues().map((r => {
r.forEach(c => {
c.replace(/\r\n/, ' ')
});
return r;
}));
//new parameters
const dlm = '|';
const dlmrow = { l: ':---', c: ':---:', r: '---:' };
const aline = (aligntext.length > 0) ? aligntext : align;
if (redactrange) {
const rgA1 = redactrange.split(',');
//Logger.log(rgA1);
const rgA = rgA1.map(function (A1, i) {
return sh.getRange(A1);
});
const rowStart = drg.getRow();
const colStart = drg.getColumn();
//const rowEnd=drg.getRow()+drg.getHeight()-1;
//const colEnd=drg.getColumn()+drg.getWidth()-1;
rgA.forEach(function (rg, k) {
var v = rg.getDisplayValues();
let row = rg.getRow();
let col = rg.getColumn();
v.forEach(function (r, i) {
r.forEach(function (c, j) {
vA[row - rowStart + i][col - colStart + j] = redactstring;//redact string
});
});
});
}
Logger.log(headers);
if (headers && headers.length > 0) {
vA.unshift(headers.split(','));
}
var tsv = '';
var hdr = [vA.shift()];
//header row
hdr.forEach(function (r, i) { tsv += dlm; r.forEach(function (c, j) { if (j > 0) tsv += dlm; tsv += c; }); tsv += dlm; });
tsv += '\r\n';
if(rows && rows.length > 0) {
tsv = dlm + tsv + dlm + ':---:';
}
//delimiter row
hdr.forEach(function (r, i) { tsv += dlm; r.forEach(function (c, j) { if (j > 0) tsv += dlm; tsv += dlmrow[aline[j % aline.length]]; }); tsv += dlm; });
tsv += '\r\n';
//data table
if(rows && rows.length > 0) {
let rA = rows.split(",");
vA.forEach(function (r, i) { if (i > 0) { tsv += '\r\n'; } tsv += dlm + rA[i] + dlm; r.forEach(function (c, j) { if (j > 0) { tsv += dlm; } tsv += c; }); tsv += dlm; });
} else {
vA.forEach(function (r, i) { if (i > 0) { tsv += '\r\n'; } tsv += dlm; r.forEach(function (c, j) { if (j > 0) { tsv += dlm; } tsv += c; }); tsv += dlm; });
}
let s = `Data:${datarange} - Redact:${redactrange}`;
var html = Utilities.formatString('<body><input type="button" value="Exit" onClick="google.script.host.close();" /><br /><textarea rows="1" cols="150" id="rngs">%s</textarea><br /><textarea rows="30" cols="150" id="tsv">%s</textarea></body>', s, tsv);
html += '<br /><input type="button" value="Exit" onClick="google.script.host.close();" />';
console.log(html);
var ui = HtmlService.createHtmlOutput(html).setWidth(800);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Table Markdown');
}
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
select,
input {
margin: 2px 5px 2px 0;
font-size: 12px;
}
#cols {
margin: 2px 5px 2px 5px;
font-size: 12px;
}
.bold {
font-weight: "bold";
}
</style>
</head>
<body>
<form name="form">
<br /><input type="text" id="dtrg" name="datarange" placeholder="Select Data Range" size="20" readonly /><input type="button" value="Data" onClick="getDataRange();" title="Select Data Range." /><input type="text" id="cols" name="cols" size="2" readonly />Cols
<br /><input type="text" id="rdrg" name="redactrange" placeholder="Select Redact Ranges" size="20" readonly /><input type="button" value="Redact" onClick="getRedactRangelist();" title="Select Redact Rangelist." />
<br /><input type="text" id= "hdrs" name="headers" placeholder="Enter Column Header Separated by Comma" size="30" /><input type="button" id="autocol" value="auto" onClick="autoCols();" />
<br /><input type="text" id= "rows" name="rows" placeholder="Enter Row Numbers Separated by Comma" size="30" /><input type="button" id="autorow" value="auto" onClick="autoRows();" />
<br /><span class="bold">Alignment</span>
<br /><select name="align"><option value="l">left</option><option value="c">center</option><option value="r">right</option></select>
<input type="text" id="alntxt" name="aligntext" placeholder="Align all columns with r,c,or l only" size="25" oninput="getLength();" /><input type="text" name="col" id="col" size="2" readonly />
<br /><input type="text" id="rs" name="redactstring" size="15" />Redact String
<br /><input type="button" value="Submit" onClick="processForm(this.parentNode);" />
</form>
<script>
$(function(){
google.script.run
.withSuccessHandler(function(obj){
if(obj.datarange) {$('#dtrg').val(obj.datarange);}
if(obj.redactrange) {$('#rdrg').val(obj.redactrange);}
if(obj.align) {$('#aln').val(obj.align);}
if(obj.redactstring) {$('#rs').val(obj.redactstring);}
if(obj.aligntext){$('$alntxt').val(obj.aligntext);}
})
.getTablePresets();
});
function getLength() {
let s=$('#alntxt').val();
let all='rlc';
if(!all.includes(s[s.length-1])){
$('#alntxt').val(s.slice(0,-1));
}
$('#col').val($('#alntxt').val().length);
}
function getDataRange() {
google.script.run
.withSuccessHandler(function(obj){
$('#dtrg').val(obj.datarange);
$('#cols').val(obj.columns);
})
.getCSVDataRange();
}
function getRedactRangelist() {
google.script.run
.withSuccessHandler(function(obj){
$('#rdrg').val(obj.redactrange);
})
.getRedactRangeList();
}
function processForm(form) {
google.script.run.redactableDataTable(form);
}
function autoCols() {
let s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
google.script.run
.withSuccessHandler((obj) => {
console.log(JSON.stringify(obj));
let hs = s.slice(obj.col - 1,obj.col + obj.width -1);
document.getElementById("hdrs").value = hs.split("").join(',');
})
.getUpperLeft();
}
function autoRows() {
google.script.run
.withSuccessHandler((obj) => {
let rs = obj.row;
document.getElementById("rows").value = Array.from(new Array(obj.height).keys(),x => x + rs).join(",");
})
.getUpperLeft();
}
console.log('My Code');
</script>
</body>
</html>
这是一个用于创建 Markdown 的简单 Web 应用程序。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<style>
textarea {
width: 100%;
height: 40vh;
}
</style>
<title>1</title>
</head>
<body>
<label
>Paste Google sheets copied content here
<textarea
id="input"
placeholder="Category Date Amount
Interest 1/1/2025 $5,000.00
Tax 2/2/2025 $3,500.00"
></textarea>
</label>
<label>
Output
<textarea
id="output"
placeholder="Category|Date|Amount
|-|-|-
Interest|1/1/2025|$5,000.00
Tax|2/2/2025|$3,500.00"
></textarea>
</label>
<script>
const inputArea = document.querySelector('#input');
inputArea.addEventListener('paste', handlePaste);
inputArea.addEventListener('change', handleChange);
async function handlePaste(e) {
try {
handleChange(e, e.clipboardData.getData('text/plain'));
} catch (e) {}
}
async function handleChange(e, data = inputArea.value) {
const num_cols = data.match(/(.*?\n)/)[0].split('\t').length;
const o = data
.replace(/^/gm, '|')
.replace('\n', '\n' + '|-'.repeat(num_cols) + '\n')
.replace(/\t/g, '|');
document.querySelector('#output').value = o;
try {
await navigator.clipboard.writeText(o);
alert('Data copied to clipboard!');
} catch (e) {
alert('Markdown generated. Copy from output below');
}
}
</script>
</body>
</html>
例如,上面粘贴的 Google 表格数据副本
Category Date Amount
Interest $5,000.00
Tax 2/2/2025
将成为
|Category|Date|Amount
|-|-|-
|Interest||$5,000.00
|Tax|2/2/2025|
将呈现为
类别 | 日期 | 金额 |
---|---|---|
兴趣 | $5,000.00 | |
税 | 2025 年 2 月 2 日 |