Skip to content

Commit defc582

Browse files
authored
Merge pull request #235 from SyncfusionExamples/ExcelChatbotWithAI
ExcelChatbotWithAI with XlsIO
2 parents 71ca30d + 0fc3b9c commit defc582

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36109.1 d17.14
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelChatBot", "ExcelChatBot\ExcelChatBot.csproj", "{835F8C64-7AEF-4936-A643-6FAFECF88AFC}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{835F8C64-7AEF-4936-A643-6FAFECF88AFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{835F8C64-7AEF-4936-A643-6FAFECF88AFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{835F8C64-7AEF-4936-A643-6FAFECF88AFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{835F8C64-7AEF-4936-A643-6FAFECF88AFC}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {D726F656-F0EE-4360-85B8-564E505CE54A}
24+
EndGlobalSection
25+
EndGlobal
Binary file not shown.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="OpenAI" Version="2.5.0" />
12+
<PackageReference Include="Syncfusion.XlsIO.Net.Core" Version="*" />
13+
</ItemGroup>
14+
15+
</Project>
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Syncfusion.XlsIO;
7+
using OpenAI;
8+
using OpenAI.Chat;
9+
using System.ClientModel;
10+
11+
/// <summary>
12+
/// HumanExcelChatBot: An AI-powered chatbot for summarizing and querying Excel workbooks using Syncfusion XlsIO and OpenAI.
13+
/// </summary>
14+
class HumanExcelChatBot
15+
{
16+
/// <summary>
17+
/// Entry point for the HumanExcelChatBot application.
18+
/// </summary>
19+
static async Task Main()
20+
{
21+
// Replace with your actual OpenAI API key or set it in environment variables for security
22+
string? openAIApiKey = "OpenAI API Key";
23+
await ExecuteChatWithExcel(openAIApiKey);
24+
}
25+
26+
/// <summary>
27+
/// Execute chat with Excel document.
28+
/// </summary>
29+
private async static Task ExecuteChatWithExcel(string openAIApiKey)
30+
{
31+
Console.WriteLine("AI Powered Excel ChatBot");
32+
33+
Console.WriteLine("Enter full Excel file path (e.g., C:\\Data\\report.xlsx):");
34+
35+
//Read user input for Excel file path
36+
string? excelFilePath = Console.ReadLine()?.Trim().Trim('"');
37+
38+
if (string.IsNullOrWhiteSpace(excelFilePath) || !File.Exists(excelFilePath))
39+
{
40+
Console.WriteLine("Invalid path. Exiting.");
41+
return;
42+
}
43+
44+
45+
if (string.IsNullOrWhiteSpace(openAIApiKey))
46+
{
47+
Console.WriteLine("OPENAI_API_KEY not set. Exiting.");
48+
return;
49+
}
50+
51+
string csvContext;
52+
try
53+
{
54+
// Convert Excel to CSV-like context
55+
csvContext = BuildCsvContext(excelFilePath);
56+
}
57+
catch (Exception ex)
58+
{
59+
Console.WriteLine($"Failed to read Excel: {ex.Message}");
60+
return;
61+
}
62+
63+
Console.WriteLine("\nOverview (AI):");
64+
65+
List<ChatMessage> chatHistory = new List<ChatMessage>
66+
{
67+
new SystemChatMessage("You are an assistant that helps analyze Excel data.")
68+
};
69+
70+
try
71+
{
72+
// Get an overview of the Excel data
73+
string overview = await AskOpenAIAsync(
74+
openAIApiKey,
75+
model: "gpt-5", // replace with a model available in your account
76+
systemPrompt: "You are a helpful assistant. Provide a concise 3-6 bullet summary of the workbook data.",
77+
userContent: csvContext, chatHistory);
78+
Console.WriteLine(overview);
79+
}
80+
catch (Exception ex)
81+
{
82+
Console.WriteLine($"OpenAI overview failed: {ex.Message}");
83+
}
84+
85+
Console.WriteLine("\nDo you want any specific details? Type 'Stop' to exit.");
86+
87+
88+
89+
while (true)
90+
{
91+
// Read user question
92+
Console.Write("\nYou: ");
93+
94+
string? userQuestion = Console.ReadLine();
95+
96+
if (userQuestion == null)
97+
continue;
98+
99+
if (userQuestion.Trim().Equals("Stop", StringComparison.OrdinalIgnoreCase))
100+
break;
101+
102+
// Define system prompt for the chatbot
103+
string systemPrompt = @"You are an intelligent Excel assistant built using Syncfusion XlsIO and OpenAI. Your job is to help users understand, analyze, and interact with Excel data through natural language. You are integrated into a C# application and can access structured Excel content such as tables, charts, formulas, and cell values.
104+
Your capabilities include:
105+
- Summarizing Excel sheets and ranges
106+
- Answering questions about data trends, totals, averages, and comparisons
107+
- Explaining formulas and calculations
108+
- Suggesting improvements or insights based on the data
109+
- Responding in a friendly, professional, and concise manner
110+
Constraints:
111+
You do not generate or modify Excel files directly. Instead, you interpret and explain the data provided to you by the application.
112+
Always assume the user is referring to the most recent Excel content unless stated otherwise. Maintain context across the conversation to provide coherent and helpful responses.
113+
If the user asks something outside the scope of Excel data, politely redirect them back to Excel-related tasks.";
114+
115+
string userPrompt =
116+
"Question:\n" + userQuestion;
117+
118+
try
119+
{
120+
// Get answer from OpenAI based on user question and chat history
121+
string answer = await AskOpenAIAsync(openAIApiKey, "gpt-5", systemPrompt, userPrompt, chatHistory);
122+
Console.WriteLine("ChatBot: " + answer);
123+
}
124+
catch (Exception ex)
125+
{
126+
Console.WriteLine($"OpenAI error: {ex.Message}");
127+
}
128+
}
129+
}
130+
131+
/// <summary>
132+
/// Builds a CSV-like text context from the specified Excel file, limited to a maximum number of rows per sheet.
133+
/// </summary>
134+
/// <param name="maxRowsPerSheet">Maximum number of rows to include per sheet.</param>
135+
/// <returns>CSV-like string representation of the workbook.</returns>
136+
private static string BuildCsvContext(string excelFilePath)
137+
{
138+
// Initialize Syncfusion Excel engine
139+
using ExcelEngine excelEngine = new ExcelEngine();
140+
141+
// Set default version to XLSX
142+
IApplication excelApp = excelEngine.Excel;
143+
excelApp.DefaultVersion = ExcelVersion.Xlsx;
144+
145+
// Open the Excel file
146+
using FileStream fileStream = File.OpenRead(excelFilePath);
147+
IWorkbook workbook = excelApp.Workbooks.Open(fileStream);
148+
149+
// Build CSV-like context
150+
StringBuilder stringBuilder = new StringBuilder();
151+
152+
// Add file and sheet info
153+
stringBuilder.AppendLine($"File: {excelFilePath}");
154+
stringBuilder.AppendLine($"Sheets: {workbook.Worksheets.Count}");
155+
stringBuilder.AppendLine();
156+
157+
// Convert each worksheet to CSV format and append to the context
158+
foreach (IWorksheet worksheet in workbook.Worksheets)
159+
{
160+
MemoryStream csvStream = new MemoryStream();
161+
162+
// Save workbook as CSV
163+
worksheet.SaveAs(csvStream, ",");
164+
165+
// Convert CSV to text
166+
string excelData = Encoding.UTF8.GetString(csvStream.ToArray());
167+
stringBuilder.AppendLine("Sheet Name : " + worksheet.Name);
168+
stringBuilder.AppendLine();
169+
stringBuilder.AppendLine(excelData);
170+
stringBuilder.AppendLine();
171+
}
172+
173+
return stringBuilder.ToString();
174+
}
175+
176+
/// <summary>
177+
/// Sends a chat completion request to OpenAI and returns the response.
178+
/// </summary>
179+
/// <param name="apiKey">OpenAI API key.</param>
180+
/// <param name="model">Model name.</param>
181+
/// <param name="systemPrompt">System prompt for the assistant.</param>
182+
/// <param name="userContent">User content/question.</param>
183+
/// <param name="chatHistory">Chat History</param>
184+
/// <returns>AI-generated response as a string.</returns>
185+
private static async Task<string> AskOpenAIAsync(string apiKey, string model, string systemPrompt, string userContent, List<ChatMessage> chatHistory)
186+
{
187+
// Initialize OpenAI client
188+
OpenAIClient openAIClient = new OpenAIClient(apiKey);
189+
190+
// Create chat client for the specified model
191+
ChatClient chatClient = openAIClient.GetChatClient(model);
192+
193+
// Append system and user messages to chat history
194+
chatHistory.Add(new SystemChatMessage(systemPrompt));
195+
196+
// Add user message to chat history
197+
chatHistory.Add(new UserChatMessage(userContent));
198+
199+
//Get AI response
200+
ClientResult<ChatCompletion> chatResult = await chatClient.CompleteChatAsync(chatHistory);
201+
202+
string response = chatResult.Value.Content[0].Text ?? string.Empty;
203+
204+
// Add assistant response to chat history
205+
chatHistory.Add(new AssistantChatMessage(response));
206+
207+
return response;
208+
}
209+
}

0 commit comments

Comments
 (0)