새 창에서 데모를 열어 디자이너 열기
이 예제는 AI 기반의 수식 생성 및 설명 기능을 보여주며, 스프레드시트와 유사한 환경에서 수식을 보다 쉽게 작성하고 이해할 수 있도록 돕는 것을 목표로 합니다.
이 기능에는 다음이 포함됩니다:
AI 수식 생성: 사용자의 입력 또는 문맥(예: "금액의 합계", "판매의 평균값")을 기반으로 수식을 자동으로 생성합니다.
수식 설명: 생성된 수식 또는 기존 수식에 대해 단계별로 자세한 설명을 제공하여, 사용자가 수식의 논리와 활용 방식을 이해할 수 있도록 도와줍니다.
이 기능을 사용하려면 다음 단계를 따르세요:
예를 들어 “'table1'에는 각 영업 사원의 판매 데이터가 포함되어 있습니다. 각 영업 사원의 판매 실적을 집계하고, 그 중 판매 실적이 가장 높은 사원을 찾아주는 수식을 알려주세요.”와 같이 쿼리를 입력하세요.
“수식 생성” 버튼을 클릭하면, 입력한 내용에 맞춰 AI가 생성한 맞춤형 수식을 확인할 수 있습니다.
수식을 검토한 후, 바로 스프레드시트에 적용할 수 있습니다.
수식 편집기 패널에 있는 모든 수식에 대해 “수식 설명”을 클릭하면, 해당 수식이 어떻게 작동하는지 단계별로 분해된 설명을 확인할 수 있습니다.
이 기능은 사용자가 이전의 스프레드시트 경험과 상관없이 더욱 효율적이고 자신 있게 수식을 사용할 수 있도록 돕습니다.
AI 생성 콘텐츠에 대한 면책 조항
1. 콘텐츠 생성 위험
본 서비스는 사용자가 주입한 제3자 AI 모델을 활용하여 출력을 생성합니다. 모델의 구조와 학습 데이터의 한계로 인해 결과물에는 부정확한 내용, 누락 또는 오해의 소지가 있을 수 있습니다. 저희는 프롬프트 엔지니어링과 기술적 제약을 통해 출력을 최적화하고 있지만, 모델 결함으로 인한 오류 위험을 완전히 제거할 수는 없습니다.
2. 사용자 검증 의무
본 서비스를 이용함으로써 귀하는 다음 사항에 동의하고 이를 준수할 것을 약속합니다:
모든 생성된 콘텐츠를 수동으로 검토할 것
검증되지 않은 출력을 법률, 의료, 금융 등 고위험 분야에서 사용하지 않을 것
생성된 콘텐츠에 의존하여 발생한 모든 직접적 또는 간접적 손실은 전적으로 사용자 책임임
3. 기술적 한계
우리는 다음과 같은 상황에 대해 책임지지 않습니다:
제3자 모델 결함 또는 논리적 오류로 인한 출력 실패
오류 복구 메커니즘에서 오류를 성공적으로 복구하지 못한 경우
현재 AI 기술의 본질적인 기술적 한계
4. 지식재산권 준수
귀하는 다음 사항을 보장해야 합니다:
주입된 모델/콘텐츠가 제3자의 권리를 침해하지 않을 것
본 서비스를 통해 불법 또는 민감한 자료를 처리하지 않을 것
모델 제공자의 지식재산권 관련 약관을 준수할 것
5. 약관 업데이트
우리는 다음과 같은 사유로 본 약관을 수정할 권리를 보유합니다:
기술 발전 (예: 새로운 AI 안전 프로토콜)
법규 변경 (예: AI 거버넌스 프레임워크 업데이트)
서비스 구조 개선
let designer, spread;
window.onload = function () {
const spread = createSpreadAndDesigner();
injectAI(spread);
initData(spread);
};
function initData(spread) {
spread.suspendPaint();
spread.options.allowDynamicArray = true;
var sheet = spread.sheets[0];
sheet.setValue(0, 0, "Grade");
sheet.setValue(0, 6, 72);
sheet.setFormula(
0,
1,
'=LET(score, G1, IF(score >= 90, "A", IF(score >= 80, "B", IF(score >= 70, "C", IF(score >= 60, "D", "F")))))'
);
sheet.setValue(1, 0, "Most Frequent");
sheet.setArray(1, 6, [[1, 2, 6, 6, 6, 5]]);
sheet.setFormula(
1,
1,
'=LET(data, G2:L2, unique_data, UNIQUE(data), count_data, COUNTIF(data, unique_data), max_count, MAX(count_data), most_frequent, INDEX(unique_data, MATCH(max_count, count_data, 0)), IF(max_count > 1, most_frequent, ""))'
);
sheet.setValue(2, 0, "GUID");
sheet.setFormula(
2,
1,
'=CONCATENATE(DEC2HEX(RANDBETWEEN(0, 4294967295), 8), "-", DEC2HEX(RANDBETWEEN(0, 65535), 4), "-", DEC2HEX(RANDBETWEEN(16384, 20479), 4), "-", DEC2HEX(RANDBETWEEN(32768, 49151), 4), "-", DEC2HEX(RANDBETWEEN(0, 65535), 4), DEC2HEX(RANDBETWEEN(0, 4294967295), 8))'
);
sheet.setActiveCell(0, 1);
const showDesigner = top === window;
if (!showDesigner) {
document.getElementById("location").innerText = "Sheet1>B1";
}
sheet.setColumnWidth(0, 100);
const dataSource = [
["name", "product", "date", "amount", "price", "sales"],
["chris", "desk", new Date("2020-10-08T16:00:00.000Z"), 5, 199, 995],
["radow", "pen", new Date("2020-09-15T16:00:00.000Z"), 2, 5, 10],
["peyton", "pencil", new Date("2021-06-22T16:00:00.000Z"), 6, 1.5, 9],
["johnson", "chair", new Date("2021-07-19T16:00:00.000Z"), 7, 68, 476],
["vic", "notebook", new Date("2021-01-13T16:00:00.000Z"), 7, 3.2, 22.4],
["lan", "desk", new Date("2021-03-12T16:00:00.000Z"), 9, 199, 1791],
["chris", "pen", new Date("2021-03-06T16:00:00.000Z"), 4, 5, 20],
["chris", "pencil", new Date("2020-09-02T16:00:00.000Z"), 10, 1.5, 15],
["radow", "chair", new Date("2020-08-09T16:00:00.000Z"), 3, 68, 204],
["peyton", "notebook", new Date("2021-02-08T16:00:00.000Z"), 9, 3.2, 28.8],
["johnson", "desk", new Date("2021-07-03T16:00:00.000Z"), 7, 199, 1393],
["vic", "pen", new Date("2021-06-27T16:00:00.000Z"), 8, 5, 40],
["lan", "pencil", new Date("2020-10-10T16:00:00.000Z"), 2, 1.5, 3],
["chris", "chair", new Date("2021-03-04T16:00:00.000Z"), 2, 68, 136],
["chris", "notebook", new Date("2021-02-21T16:00:00.000Z"), 11, 3.2, 35.2],
["radow", "desk", new Date("2021-06-03T16:00:00.000Z"), 6, 199, 1194],
];
sheet.setArray(5, 0, dataSource);
sheet.tables.add("table1", 5, 0, 17, 6);
spread.resumePaint();
}
function createSpreadAndDesigner() {
const demoHost = document.getElementById("demo-host");
if (window !== top) {
const spread = new GC.Spread.Sheets.Workbook(demoHost, { sheetCount: 1 });
const formulaEditor = new GC.Spread.Sheets.FormulaPanel.FormulaEditor(
document.getElementById("editor")
);
formulaEditor.attach(spread);
const save_btn = document.getElementById("save");
save_btn.addEventListener("click", () => {
formulaEditor
.commandManager()
.execute({ cmd: "commitContentToActiveCell" });
});
const location = document.getElementById("location");
spread.bind("ActiveCellChanged", (eventType, args) => {
location.innerText = `${spread.getActiveSheet().name()}>${toColumnIndex(
args.col
)}${args.row + 1}`;
});
return spread;
} else {
const designer = new GC.Spread.Sheets.Designer.Designer(
demoHost,
undefined,
undefined,
{ sheetCount: 1 }
);
const panel = document.getElementById("panel");
panel.style.display = "none";
designer.setData("formulaEditorPanel_Visible", true);
return designer.getWorkbook();
}
}
function toColumnIndex(index) {
let column = "";
while (index >= 0) {
column = String.fromCharCode((index % 26) + 65) + column;
index = Math.floor(index / 26) - 1;
}
return column;
}
function injectAI(spread) {
const serverCallback = async (requestBody) => {
const response = await fetch(getAIApiUrl(), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
});
if (response.status === 429) {
alert('The server is busy, please try again later.');
return;
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response;
};
spread.injectAI(serverCallback);
}
function getAIApiUrl() {
return (
window.location.href.match(/http.+spreadjs\/learn-spreadjs\//)[0] + 'server/api/queryAI'
);
}
<!DOCTYPE html>
<html style="height: 100%; font-size: 14px">
<head>
<meta charset="utf-8" />
<meta name="spreadjs culture" content="ko-kr" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
type="text/css"
href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"
/>
<link
rel="stylesheet"
type="text/css"
href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"
/>
<script
src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js"
type="text/javascript"
></script>
<script
src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js"
type="text/javascript"
></script>
<script
src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-ai-addon/dist/gc.spread.sheets.ai.min.js"
type="text/javascript"
></script>
<script
src="$DEMOROOT$/spread/source/js/license.js"
type="text/javascript"
></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-resources-ko/dist/gc.spread.sheets.resources.ko.min.js" type="text/javascript"></script>
<script>
const designerDependencyScripts = [
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-resources-ko/dist/gc.spread.sheets.resources.ko.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer-resources-ko/dist/gc.spread.sheets.designer.resource.ko.min.js",
"$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js",
"$DEMOROOT$/spread/source/js/designer/license.js",
];
function appendScriptNode(src) {
const script = document.createElement("script");
script.src = src;
script.async = false;
script.type = "text/javascript";
document.head.appendChild(script);
}
if (top === window) {
// not in iframe
designerDependencyScripts.forEach(appendScriptNode);
}
</script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body>
<div class="sample-tutorial">
<div id="demo-host"></div>
<div id="panel">
<div id="header">
<div id="save"></div>
<div id="location"></div>
</div>
<div id="editor"></div>
</div>
</div>
</body>
</html>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: row;
}
#demo-host {
width: 69vw;
height: 100%;
flex-grow: 1;
}
#panel {
margin-left: 10px;
width: 30vw;
display: flex;
flex-direction: column;
}
#header {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
#save {
margin-left: 7px;
height: 30px;
width: 30px;
cursor: pointer;
background-position: center;
background-repeat: no-repeat;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNiIgaGVpZ2h0PSIyNiI+PGcgZmlsbD0iIzY5Njk2OSIgZmlsbC1ydWxlPSJub256ZXJvIj48cGF0aCBzdHJva2U9IiM2NjYiIHN0cm9rZS13aWR0aD0iLjciIGQ9Ik0xMC44NzIgMnEuNTgyIDAgLjkzNS4yOS4zNTUuMjg4LjM1NC42MjQtLjAwMS4yNy0uMTc2LjQ0N2EuNjIuNjIgMCAwIDEtLjQ1NC4xNzcuNTcuNTcgMCAwIDEtLjM5Mi0uMTM0LjQyLjQyIDAgMCAxLS4xNTMtLjMyM3EwLS4xMi4xMDEtLjI5OS4xLS4xNzUuMS0uMjMzYS4yLjIgMCAwIDAtLjA2Ni0uMTU4cS0uMDk2LS4wNzUtLjI4Ny0uMDc1LS40ODggMC0uODcuMjk5LS41MTUuNDAxLS45MjYgMS4yNS0uMjEuNDM4LS43NjQgMi4yMDFoMS4xMzdsLS4xNDQuNDk2SDguMTVMNy4zIDkuODQ0cS0uNTYzIDIuMTY0LTEuMTI3IDMuMzU4LS44MSAxLjY3LTEuNzM4IDIuMzAzUTMuNzMgMTYgMy4wMjIgMTZxLS40NjggMC0uNzgzLS4yNzFBLjU5LjU5IDAgMCAxIDIgMTUuMjQ1cTAtLjI0MS4xOTYtLjQyMWEuNjguNjggMCAwIDEgLjQ3My0uMTc2cS4yMSAwIC4zNTMuMTI2YS4zOC4zOCAwIDAgMSAuMTQzLjI5NHEwIC4xNjYtLjE2Mi4zMDgtLjEyNC4xMDEtLjEyNC4xNTggMCAuMDY1LjA1Ny4xMDIuMDY4LjA1Ny4yMS4wNTcuMzM0IDAgLjY5Ny0uMjA2LjM2My0uMjA1LjY1LS42MDYuMjg1LS40MDIuNTQ0LTEuMTU2LjEwNS0uMzE4LjU3My0yLjA4MWwxLjMzNy01LjA4Mkg1LjYxbC4xMDUtLjQ5NXEuNjQgMCAuODkzLS4wODkuMjUzLS4wODguNDYzLS4zMzIuMjEtLjI0MS41NTQtLjkxNC40NDktLjg5NC44NjktMS4zODkuNTYzLS42NzEgMS4xOTQtMS4wMDguNjMtLjMzNiAxLjE4NC0uMzM1Wm00LjQxMSAzLjg4MXEuMzI2IDAgLjUyMS4xNzYuMTk2LjE3Ny4xOTYuNDE5IDAgLjI5LS4xMTQuMzkzYS43MS43MSAwIDAgMS0uNDg3LjE4NnEtLjE2NC4wMDItLjM1NC0uMDY2LS4zNTMtLjEyLS40NzgtLjEyLS4xOSAwLS40MzkuMjA0LS40NzguMzk0LTEuMTM3IDEuNTFsLjYzMiAyLjU4NnEuMTQzLjU5Ny4yNDMuNzEyLjEuMTE5LjE5NS4xMTguMTYyIDAgLjM4My0uMTc2YTMuMSAzLjEgMCAwIDAgLjcyNi0uODk2bC4yNjcuMTI5YTQuOCA0LjggMCAwIDEtMS4yMzMgMS40NzRxLS40Mi4zMjYtLjcxNS4zMjYtLjQzLjAwMS0uNjg4LS40NjYtLjE2Mi0uMjk3LS42Ny0yLjUyOC0xLjE5MyAyLjAzNS0xLjkxOCAyLjYyLS40NjguMzc0LS45MDcuMzc0YS44Ni44NiAwIDAgMS0uNTY0LS4yMTUuNTguNTggMCAwIDEtLjE4Mi0uNDQ4LjU2OC41NjggMCAwIDEgLjU4My0uNTc3cS4yNDggMCAuNTI2LjI0My4yLjE3Ni4zMDUuMTc2LjA5NSAwIC4yMzktLjEyLjM2My0uMjkuOTgzLTEuMjM3LjYyLS45NDYuODEzLTEuMzY2YTEwMCAxMDAgMCAwIDAtLjUwNy0xLjkzMmMtLjEyMi0uMzItLjI3Ny0uNTUyLS40NjgtLjY4NXEtLjI4Ny0uMi0uODMxLS4xOTktLjE4MSAwLS40MS4wMDl2LS4yNzFsMi4wNTQtLjM1M3EuMzcuMzkxLjU2My43ODMuMTQyLjI3LjQ1OCAxLjQxOGwuNjc3LS45ODlxLjI2OS0uMzY0LjY1LS42OS4zODItLjMyOC42NzktLjQzOGEuOTYuOTYgMCAwIDEgLjQxLS4wODRaIi8+PHBhdGggZD0ibTExLjcxMiAyNS4yNi0uNjE3LS42MDdMNCAxOC43MjZsMS40NDItMS40ODYgNi4yNyA1LjE1NUwyMy42NiAxMCAyNSAxMS4yMzYgMTIuMzAxIDI0LjY1MyIvPjwvZz48L3N2Zz4=);
}
#save:hover {
transform: scale(1.1);
}
#location {
margin-left: 12px;
line-height: 30px;
font-size: 18px;
}
#editor {
height: calc(100% - 30px);
}