Please enter the password to access the Bronze Workbook.
Incorrect password!
Edit Content
Bronze Workbook
Smart Synchronization System
Cloud Configuration
Status: Ready
This is the information page of STEAMAX Joint Stock Company to help students complete their CREST profiles most effectively.
Bronze Workbook Sync
Smart synchronization system. Data between tables is automatically mirrored to save you time.
Workbook User Guide
Tip: Click on any English text with a dashed underline to see its Vietnamese translation! (Try it here)
1. How to fill in
Click on any text box, a large whiteboard will appear for you to comfortably read and write long texts without being hidden.
Click the "Guide" button at the right corner of each table to see prompt questions and specific examples.
Note: Grey background cells with blue text are automatically "mirrored" (copied) from previous tables. You don't need to re-enter them!
2. Where is data saved?
When you click "Sync to Cloud", everything you wrote will automatically be drawn into beautiful tables in your Google Doc.
Attached images, videos, and evidence will be saved directly to the Google Drive Folder you linked in the left sidebar.
3. What does this tool support?
Save time: Eliminate copy/pasting the same info thanks to auto-sync between steps.
CREST Standardization: Question structure closely follows 100% of the CREST Bronze certification criteria.
Automated reporting: Automatically generate a proper Report file without manual Word formatting.
Team Information
1
The Biggest Problem to Solve
Root Cause Analysis
Solution
Short Description
Pros
Cons
Stakeholders: Participants / Resources
2
Analyze Solution Criteria
Characteristics
Criteria
How to test
Solution
Success
3
Analyze Current Status & Set Action Steps
Solution
Current state of materials
Action Steps
Outcomes
Applied Knowledge
Group Tasks
Action Steps (Mirrored)
Task
Who’s responsible?
What help might I/we need?
What resources do I/we need?
Completed by when?
Finished?
Challenge
Improvement
5
Model Testing
Test Criteria (Mirrored)
Trial
Test Conditions
Measured Variables
Results
Improvements
6
What you have learned from this project
7
Presentation and Project Communication
Content you will present
Your presentation format
Guide
Google Apps Script Code
Smart Merge Version (Intelligent update, avoids duplicates, safely keeps old data)
DEPLOYMENT STEPS: 1. Open Apps Script from Google Doc. 2. Paste code below. 3. Save (Ctrl+S). 4. Click Deploy > New deployment. 5. Type: Web app. 6. Access: Anyone. 7. Copy the web app URL and paste it into the left sidebar.
function doPost(e) {
try {
const data = JSON.parse(e.postData.contents);
const doc = DocumentApp.openByUrl(data.docUrl);
const body = doc.getBody();
// --- SMART MERGE LOGIC ---
// Helper: Find existing paragraph by text
function findParagraphByText(text) {
let paras = body.getParagraphs();
for (let i = 0; i < paras.length; i++) {
if (paras[i].getText().indexOf(text) !== -1) {
return paras[i];
}
}
return null;
}
// Helper: Check if row exactly matches an existing row in a table to prevent duplicates
function rowExistsInTable(table, rowData) {
for (let r = 0; r < table.getNumRows(); r++) {
let row = table.getRow(r);
if (row.getNumCells() === rowData.length) {
let match = true;
for (let c = 0; c < row.getNumCells(); c++) {
if (row.getCell(c).getText().trim() !== String(rowData[c]).trim()) {
match = false;
break;
}
}
if (match) return true;
}
}
return false;
}
// Process data iteratively
data.sections.forEach(sec => {
// 1. Ensure Section Heading exists
let secHeading = findParagraphByText(sec.name);
if (!secHeading) {
secHeading = body.appendParagraph(sec.name).setHeading(DocumentApp.ParagraphHeading.HEADING2).setSpacingBefore(30).setSpacingAfter(10);
}
sec.content.forEach(item => {
if (item.type === 'field') {
let prefix = item.label + ":";
let fieldPara = findParagraphByText(prefix);
if (!fieldPara) {
// Field not found -> Create new paragraph
const p = body.appendParagraph("");
p.appendText(prefix + " ").setBold(true).setFontSize(11);
p.appendText(item.value).setBold(false).setFontSize(11);
} else {
// Field found -> Check for duplicates and append new text to existing paragraph
let currentText = fieldPara.getText();
if (currentText.indexOf(item.value) === -1) {
fieldPara.appendText("\\n- " + item.value).setBold(false).setFontSize(11);
}
}
} else if (item.type === 'table') {
let tableTitlePara = findParagraphByText(item.tableName);
let targetTable = null;
if (tableTitlePara) {
let sibling = tableTitlePara.getNextSibling();
// Skip empty paragraphs to find the actual table
while(sibling && sibling.getType() === DocumentApp.ElementType.PARAGRAPH && sibling.getText().trim() === "") {
sibling = sibling.getNextSibling();
}
if (sibling && sibling.getType() === DocumentApp.ElementType.TABLE) {
targetTable = sibling.asTable();
}
}
if (!targetTable) {
// Create brand new table
body.appendParagraph(item.tableName).setItalic(true).setSpacingBefore(15).setSpacingAfter(5).setFontSize(10);
targetTable = body.appendTable(item.rows);
// Format table header
const headerRow = targetTable.getRow(0);
for (let i = 0; i < headerRow.getNumCells(); i++) {
headerRow.getCell(i).setBackgroundColor('#1e40af')
.getChild(0).asParagraph()
.setBold(true)
.setForegroundColor('#ffffff')
.setAlignment(DocumentApp.HorizontalAlignment.CENTER);
}
targetTable.setBorderColor('#e2e8f0');
} else {
// Table exists -> Append ONLY new rows
for (let r = 1; r < item.rows.length; r++) { // skip header
let rowData = item.rows[r];
if (!rowExistsInTable(targetTable, rowData)) {
let newTr = targetTable.appendTableRow();
rowData.forEach(cellData => {
newTr.appendTableCell(String(cellData));
});
}
}
}
}
});
});
// File saving logic to Drive
if (data.folderId && data.files && data.files.length > 0) {
const folder = DriveApp.getFolderById(data.folderId);
data.files.forEach(f => {
try {
const contentType = f.data.substring(5, f.data.indexOf(';'));
const bytes = Utilities.base64Decode(f.data.split(',')[1]);
const blob = Utilities.newBlob(bytes, contentType, f.name);
folder.createFile(blob);
} catch(fileError) {}
});
}
return ContentService.createTextOutput("Success.").setMimeType(ContentService.MimeType.TEXT);
} catch (err) {
return ContentService.createTextOutput("Error: " + err.message).setMimeType(ContentService.MimeType.TEXT);
}
}