Community Survey import specifier for xlsx plugin

This commit is contained in:
Jeremy Ruston
2025-07-18 14:07:20 +01:00
parent 93d30f374d
commit 8611d06eb9
11 changed files with 104 additions and 17 deletions
@@ -1,4 +1,5 @@
title: $:/DefaultTiddlers title: $:/DefaultTiddlers
HelloThere HelloThere
[[TiddlyWiki Community Survey (2025)]]
[[The Great TiddlyWiki Interview Project (2010)]] [[The Great TiddlyWiki Interview Project (2010)]]
@@ -2,6 +2,17 @@ title: HelloThere
This page gathers the responses to surveys that we have run for the TiddlyWiki community. This page gathers the responses to surveys that we have run for the TiddlyWiki community.
<%if [tag[Community Survey 2025]] %>
Surveys available:
* [[TiddlyWiki Community Survey (2025)]]
* [[The Great TiddlyWiki Interview Project (2010)]]
<%else%>
Currently, there is one survey: [[The Great TiddlyWiki Interview Project (2010)]] Currently, there is one survey: [[The Great TiddlyWiki Interview Project (2010)]]
<%endif%>
Thank you to https://yatagarasu.tiddlyhost.com for creating the palette used on this page. Thank you to https://yatagarasu.tiddlyhost.com for creating the palette used on this page.
@@ -3,23 +3,23 @@ tags: $:/tags/Stylesheet
\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock \rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock
.interview-2010 h1 button svg { .interview h1 button svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
vertical-align: middle; vertical-align: middle;
} }
.interview-2010 h2 img { .interview h2 img {
width: 32px; width: 32px;
height: 32px; height: 32px;
vertical-align: middle; vertical-align: middle;
} }
.interview-2010 h3 { .interview h3 {
font-size: 0.9em; font-size: 0.9em;
line-height: 1; line-height: 1;
} }
.interview-2010-answer { .interview-answer {
margin-left: 32px; margin-left: 32px;
} }
@@ -41,7 +41,7 @@ Here are the questions we asked and the responses we received.
<h3> <h3>
//<$view tiddler=<<answer>> field="modified" format="date" template="DDth MMM YYYY" />// //<$view tiddler=<<answer>> field="modified" format="date" template="DDth MMM YYYY" />//
</h3> </h3>
<$transclude $tiddler=<<answer>> mode="block" /> <$transclude $tiddler=<<answer>> $mode="block" />
</div> </div>
</$list> </$list>
<%endif%> <%endif%>
@@ -0,0 +1,31 @@
title: TiddlyWiki Community Survey (2025)
<$let stateBase=<<qualify "$:/state/survey-2025/">>>
<div class="interview">
<$list filter="[tag[Community Survey 2025]fields[]sort[]] -tags -title">
<$let state={{{ [<stateBase>addsuffix<currentTiddler>] }}}>
<h1>
<$button class="tc-btn-invisible">
<$action-setfield $tiddler=<<state>> $field="text" $value={{{ [<state>get[text]match[yes]then[no]else[yes]] }}}/>
<%if [<state>get[text]match[yes]] %>
{{$:/core/images/chevron-down}}
<%else%>
{{$:/core/images/chevron-right}}
<%endif%>
</$button>
<$link to=<<currentTiddler>>>
<$text text=<<currentTiddler>>/>
</$link>
</h1>
<%if [<state>get[text]match[yes]] %>
<$list filter="[tag[Community Survey 2025]]" variable="answer">
<div class="interview-answer">
<$transclude $tiddler=<<answer>> $field=<<currentTiddler>> $mode="block" />
</div>
</$list>
<%endif%>
</$let>
</$list>
</div>
</$let>
@@ -0,0 +1,9 @@
created: 20250711121107617
import-spec-role: row
import-row-type: by-column
list: [[$:/_importspec/Community Survey 2025/Content/Row/title]]
modified: 20250711121107617
tags:
title: $:/_importspec/Community Survey 2025/Content/Row
type: text/vnd.tiddlywiki
@@ -0,0 +1,10 @@
created: 20250711121107617
import-sheet-name: Content
import-spec-role: sheet
import-tags: [[Community Survey 2025]]
skip-rows-top: 3
list: [[$:/_importspec/Community Survey 2025/Content/Row]]
modified: 20250711121107617
tags:
title: $:/_importspec/Community Survey 2025/Content
type: text/vnd.tiddlywiki
@@ -0,0 +1,8 @@
caption: Import Community Survey 2025 Results Spreadsheet
created: 20250711121107617
import-spec-role: workbook
list: [[$:/_importspec/Community Survey 2025/Content]]
modified: 20250711121107617
tags:
title: $:/_importspec/Community Survey 2025/
type: text/vnd.tiddlywiki
@@ -0,0 +1,6 @@
created: 20161021164330811
modified: 20161021164331841
title: $:/config/plugins/tiddlywiki/xlsx-utils/default-import-spec
type: text/vnd.tiddlywiki
$:/_importspec/Community Survey 2025/
@@ -1,4 +1,8 @@
{ {
"plugins": [
"tiddlywiki/jszip",
"tiddlywiki/xlsx-utils"
],
"themes": [ "themes": [
"tiddlywiki/snowwhite", "tiddlywiki/snowwhite",
"tiddlywiki/vanilla" "tiddlywiki/vanilla"
+19 -12
View File
@@ -21,6 +21,7 @@ var XLSXImporter = function(options) {
this.importSpec = options.importSpec || this.wiki.getTiddlerText(DEFAULT_IMPORT_SPEC_TITLE); this.importSpec = options.importSpec || this.wiki.getTiddlerText(DEFAULT_IMPORT_SPEC_TITLE);
this.logger = new $tw.utils.Logger("xlsx-utils"); this.logger = new $tw.utils.Logger("xlsx-utils");
this.results = []; this.results = [];
this.nextAutoTitle = 1;
if(JSZip) { if(JSZip) {
this.processWorkbook(); this.processWorkbook();
} }
@@ -50,6 +51,8 @@ XLSXImporter.prototype.processSheet = function(sheetImportSpecTitle) {
this.sheetImportSpec = this.wiki.getTiddler(sheetImportSpecTitle); this.sheetImportSpec = this.wiki.getTiddler(sheetImportSpecTitle);
if(this.sheetImportSpec) { if(this.sheetImportSpec) {
this.sheetName = this.sheetImportSpec.fields["import-sheet-name"]; this.sheetName = this.sheetImportSpec.fields["import-sheet-name"];
this.skipRowsTop = $tw.utils.parseInt(this.sheetImportSpec.fields["skip-rows-top"] || "0");
this.applyTags = this.sheetImportSpec.fields["import-tags"] || "";
this.sheet = this.workbook.Sheets[this.sheetName]; this.sheet = this.workbook.Sheets[this.sheetName];
if(!this.sheet) { if(!this.sheet) {
this.logger.alert("Missing sheet '" + this.sheetName + "'"); this.logger.alert("Missing sheet '" + this.sheetName + "'");
@@ -57,11 +60,15 @@ XLSXImporter.prototype.processSheet = function(sheetImportSpecTitle) {
// Get the size of the sheet // Get the size of the sheet
this.sheetSize = this.measureSheet(this.sheet); this.sheetSize = this.measureSheet(this.sheet);
// Read the column names from the first row // Read the column names from the first row
this.columnsByName = this.findColumns(this.sheet,this.sheetSize); this.columnsByName = this.findColumns(this.sheet,this.sheetSize,this.skipRowsTop);
// Iterate through the rows // Iterate through the rows
for(this.row=this.sheetSize.startRow+1; this.row<=this.sheetSize.endRow; this.row++) { const startRow = this.sheetSize.startRow + this.skipRowsTop + 1;
// Iterate through the row import specifiers const endRow = this.sheetSize.endRow;
$tw.utils.each(this.sheetImportSpec.fields.list || [],this.processRow.bind(this)); if(startRow < endRow) {
for(this.row=startRow; this.row<=endRow; this.row++) {
// Iterate through the row import specifiers
$tw.utils.each(this.sheetImportSpec.fields.list || [],this.processRow.bind(this));
}
} }
} }
} }
@@ -85,7 +92,10 @@ XLSXImporter.prototype.processRow = function(rowImportSpecTitle) {
// Save the tiddler if not skipped // Save the tiddler if not skipped
if(!this.skipTiddler) { if(!this.skipTiddler) {
if(!this.tiddlerFields.title) { if(!this.tiddlerFields.title) {
this.logger.alert("Missing title field for " + JSON.stringify(this.tiddlerFields)); this.tiddlerFields.title = "Imported " + $tw.utils.pad(this.nextAutoTitle++,5);
}
if(this.applyTags) {
this.tiddlerFields.tags = this.applyTags;
} }
this.results.push(this.tiddlerFields); this.results.push(this.tiddlerFields);
} }
@@ -102,10 +112,6 @@ XLSXImporter.prototype.processRowByColumn = function() {
self.tiddlerFields[name] = cell.w; self.tiddlerFields[name] = cell.w;
} }
}); });
// Skip the tiddler entirely if it doesn't have a title
if(!this.tiddlerFields.title) {
this.skipTiddler = true;
}
}; };
XLSXImporter.prototype.processRowByField = function() { XLSXImporter.prototype.processRowByField = function() {
@@ -182,15 +188,16 @@ XLSXImporter.prototype.measureSheet = function(sheet) {
} }
}; };
XLSXImporter.prototype.findColumns = function(sheet,sheetSize) { XLSXImporter.prototype.findColumns = function(sheet,sheetSize,skipRowsTop) {
skipRowsTop = skipRowsTop || 0;
var columnsByName = {}; var columnsByName = {};
for(var col=sheetSize.startCol; col<=sheetSize.endCol; col++) { for(var col=sheetSize.startCol; col<=sheetSize.endCol; col++) {
var cell = sheet[XLSX.utils.encode_cell({c: col, r: sheetSize.startRow})], var cell = sheet[XLSX.utils.encode_cell({c: col, r: sheetSize.startRow + skipRowsTop})],
columnName; columnName;
if(cell) { if(cell) {
columnName = cell.w; columnName = cell.w;
if(columnName) { if(columnName) {
columnsByName[columnName] = col; columnsByName[columnName] = col;
} }
} }
} }