|

楼主 |
发表于 2025-7-26 23:32:29
|
显示全部楼层
Office.onReady((info) => {
if (info.host === Office.HostType.PowerPoint) {
document.getElementById("sideload-msg").style.display = "none";
document.getElementById("app-body").style.display = "flex";
document.getElementById("run").onclick = run;
}
});
async function readTextFile(file: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => resolve(event.target?.result as string);
reader.onerror = (error) => reject(error);
reader.readAsText(file);
});
}
function updateStatus(message: string) {
const statusBox = document.getElementById("statusBox");
if (statusBox) {
statusBox.innerHTML = statusBox.innerHTML+`${new Date().toLocaleTimeString()}: ${message}<br>`;
// 自动滚动到底部
statusBox.scrollTop = statusBox.scrollHeight;
}
}
export async function run() {
document.getElementById("statusBox").innerHTML ="";
const fileInput = document.getElementById("txtFile") as HTMLInputElement;
if (!fileInput.files || fileInput.files.length === 0) {
alert("Please select a TXT file first");
return;
}
//try {
const file = fileInput.files[0];
const fileContent = await readTextFile(file);
updateStatus("here2");
// Parse the content
const titleRegex = /<title>(.*?)<\/title>/g;
const paragraphRegex = /<p>(.*?)<\/p>/g;
let titles = [];
let titleMatch;
let originalCount=0
while ((titleMatch = titleRegex.exec(fileContent)) !== null) {
titles.push({
text: titleMatch[1],
position: titleRegex.lastIndex
});
}
updateStatus("here1");
// Get the PowerPoint context
await PowerPoint.run(async (context) => {
// Process each title section
for (let i = 0; i < titles.length; i++) {
// Add a new slide (using blank layout)
const slides = context.presentation.slides;
const newSlideProxy = slides.add();
originalCount+=1
// 3. 强制同步并重新加载全部数据
await context.sync(); // 第二次同步
// 4. 通过索引精确获取新幻灯片(绝对可靠)
const slide = slides.getItemAt(originalCount); // 新幻灯片索引=原总数
// 2. 加载所有形状(包括隐藏的占位符)
slide.load("shapes/items");
await context.sync();
const shapes = slide.shapes.items;
for (let i = shapes.length - 1; i >= 0; i--) {
shapes[i].delete();
}
await context.sync(); // 第三次同步
updateStatus(String(originalCount));
// Add title shape
const titleShape = slide.shapes.addTextBox(titles[i].text);
updateStatus(titles[i].text);
await context.sync();
titleShape.left = 20;
titleShape.top = 50;
titleShape.width = 600; // 设置宽度
titleShape.height = 50; // 设置高度
titleShape.textFrame.textRange.font.size = 24;
titleShape.textFrame.textRange.font.color = "#1E46EB";
titleShape.textFrame.textRange.font.name = "KaiTi";
// Find paragraphs between this title and next title
const startPos = titles[i].position;
const endPos = i < titles.length - 1 ? titles[i + 1].position : fileContent.length;
const sectionContent = fileContent.substring(startPos, endPos);
let paragraphMatch;
let paragraphY = 100;
while ((paragraphMatch = paragraphRegex.exec(sectionContent)) !== null) {
const contentShape = slide.shapes.addTextBox(paragraphMatch[1]);
contentShape.left = 60;
contentShape.top = paragraphY;
contentShape.width = 600; // 设置宽度
contentShape.height = 50; // 设置高度
contentShape.textFrame.textRange.font.size = 24;
contentShape.textFrame.textRange.font.color = "#000000";
contentShape.textFrame.textRange.font.name = "KaiTi";
//contentShape.textFrame.paragraphFormat.lineSpacing = 60;
paragraphY += 60;
}
slide.load("shapes");
await context.sync();
// 4. 绘制坐标轴(使用线条和文本框)
const axisColor = "#000000"; // 黑色坐标轴
const axisWidth = 2; // 线宽
// 绘制X轴
const xAxis = slide.shapes.addLine("Straight", {
left: 100, // 形状容器左边界位置(磅)
top: 300, // 形状容器上边界位置(磅)
width: 400, // 线条宽度(X轴长度)
height: 0 // 直线高度设为0
});
//3. 设置线条样式(通过lineFormat)
xAxis.lineFormat.load("color/type, weight, dashStyle, beginArrowheadStyle, endArrowheadStyle");
await context.sync();
xAxis.lineFormat.weight = 5; // 线宽(磅)
xAxis.lineFormat.color = "000000"; // 黑色
const arrow = slide.shapes.addGeometricShape("Triangle", { left: 300, top: 95, width: 5, height: 50, rotation:60});
arrow.fill.setSolidColor("000000");
// 绘制Y轴
/*const yAxis = slide.shapes.addLine(200, 100, 200, 400, {
stroke: {
color: axisColor,
width: axisWidth,
dashStyle: "solid"
}
});*/
}
await context.sync();
});
alert("Presentation created successfully!");
/*} catch (error) {
//updateStatus("Error:", error);
alert("Error creating presentation: " + error.message);
}*/
}
|
|