USING IRONWORD

ASP .NET Core Import & Export A Word File

Published December 16, 2024
Share:

Introduction

This guide explores how to import existing Word documents, display their content, and create documents from scratch using the IronWord library. By the end of this tutorial, you'll have created an ASP.NET Core web application that can:

  1. Upload and read Word documents
  2. Display the content of these documents in a textbox
  3. Export the Docx file

This project is perfect for developers who need to integrate Word document processing into their web applications, whether for document management systems, report generators, or any other scenario involving Microsoft Word files.

Prerequisites

To follow along with this tutorial, you should have:

  • Basic knowledge of C# and ASP.NET Core
  • Visual Studio 2019 or later installed (alternatively, you can use Visual Studio Code with the C# extension)
  • .NET Core SDK 3.1 or later

Don't worry if you're not an expert in these technologies – we'll guide you through each step of the process!

What is IronWord?

IronWord is a .NET library allowing developers to programmatically read, manipulate, and create Microsoft Word documents. It provides a high-level API that simplifies working with Word files, making it an excellent choice for our project.

Some key features of IronWord include:

  • Reading and writing various Word formats (DOCX, DOC, etc.)
  • Manipulating document content and structure
  • Formatting text and paragraphs
  • Working with tables, images, and other document elements
  • Mail Merge process for the Documents
  • Converting a Word document to a PDF document with ease, so you can take your final Word documents and make them easy to share PDF files

Now that we have an overview of what we're building and the tools we'll use, let's dive into setting up our project!

2. Setting up the project

In this section, we'll create a new ASP.NET Core project and install the necessary packages to work with IronWord.

2.1 Creating a new ASP.NET Core Project

  1. Open Visual Studio 2019 or later.
  2. Click on "Create a new project".

    1. Search for "ASP.NET Core Web Application" and select it.
  3. Click "Next".
  4. Name your project "WordDocumentProcessor" (or any name you prefer).
  5. Select the .NET Framework and a location for your project and click "Create".

2.2 Installing the IronWord NuGet Package

Now that we have our project set up, let's add the IronWord library:

  1. Right-click on your project in the Solution Explorer.
  2. Select "Manage NuGet Packages".

    1. In the "Browse" tab, search for "IronWord".
  3. Look for the official IronWord package.
  4. Click "Install" to add it to your project.

2.3 Updating the Existing Controller and View

Let's update our existing structure to incorporate the document processing functionality:

  1. We'll be using the existing HomeController.cs in the Controllers folder for our document processing logic.

  2. We'll update the existing Index.cshtml view in the Views/Home folder to include the document upload and display functionality.

Now that we have our project set up and the IronWord package installed, we're ready to start implementing the document import and export functionality. We'll be adding new methods to our HomeController and modifying the Index view to handle these features. In the next section, we'll focus on importing Word documents and displaying their content, utilizing our existing controller and view structure. We can add mail merge functionality as well but we'll focus on import and export documents in this article.

3. Importing Word Documents

In this section, we'll explore how to implement a feature for importing and processing Word documents in an ASP.NET MVC application. We'll cover both the user interface design and the back-end controller logic.

3.1 User Interface Design

The user interface for importing Word documents is designed to be intuitive and visually appealing. Let's break down the key components of the UI:

3.1.1 Upload Area

The upload area is the focal point of the interface, inviting users to select and upload their Word documents. Here's how it's structured:

<div class="upload-area">
    <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
    <polyline points="14 2 14 8 20 8"></polyline>
    <line x1="16" y1="13" x2="8" y2="13"></line>
    <line x1="16" y1="17" x2="8" y2="17"></line>
    <polyline points="10 9 9 9 8 9"></polyline>
</svg>
    <p>Choose a Word document</p>
    <label for="fileInput" class="choose-file">Choose File</label>
    <p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
    <button id="uploadBtn" class="upload-button">Upload and Process</button>
</div>
<div class="upload-area">
    <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
    <polyline points="14 2 14 8 20 8"></polyline>
    <line x1="16" y1="13" x2="8" y2="13"></line>
    <line x1="16" y1="17" x2="8" y2="17"></line>
    <polyline points="10 9 9 9 8 9"></polyline>
</svg>
    <p>Choose a Word document</p>
    <label for="fileInput" class="choose-file">Choose File</label>
    <p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
    <button id="uploadBtn" class="upload-button">Upload and Process</button>
</div>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<div class="upload-area"> <svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> <polyline points="10 9 9 9 8 9"></polyline> </svg> <p> Choose a Word document</p> <label for="fileInput" class="choose-file"> Choose File</label> <p class="file-info">.DOC @or.DOCX(MAX. 10MB)</p> <button id="uploadBtn" class="upload-button"> Upload @and Process</button> </div>
VB   C#

This code creates a visually appealing upload area with a file icon, a hidden file input, and a styled label acting as the file selection button. It also includes information about accepted file types and a button to initiate the upload and processing.

3.1.2 Content Display Area

After processing the document, its content is displayed in a dedicated area:

<div class="content-wrapper">
    <h2>Document Content:</h2>
    <div id="documentContent" class="content-area">
        No content to display.
    </div>
</div>
<div class="content-wrapper">
    <h2>Document Content:</h2>
    <div id="documentContent" class="content-area">
        No content to display.
    </div>
</div>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<div class="content-wrapper"> <h2> Document Content:</h2> <div id="documentContent" class="content-area"> No content @to display. </div> </div>
VB   C#

This section provides a scrollable area to display the processed document content.

3.2 Controller Implementation

The HomeController handles the server-side logic for importing and processing Word documents. Let's examine the key methods:

3.2.1 UploadAndProcess Method

This method is responsible for handling the file upload and processing:

[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return Json(new { success = false, message = "No file uploaded." });
    }
    var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
    if (fileExtension != ".doc" && fileExtension != ".docx")
    {
        return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
    }
    try
    {
        var tempFilePath = Path.GetTempFileName();
        using (var stream = new FileStream(tempFilePath, FileMode.Create))
        {
            file.CopyTo(stream);
        }
        StringBuilder contentBuilder = new StringBuilder();
        WordDocument doc = new WordDocument(tempFilePath);
        foreach (Paragraph paragraph in doc.Paragraphs)
        {
            foreach (Text textRun in paragraph.Texts)
            {
                contentBuilder.AppendLine(textRun.Text);
            }
            contentBuilder.AppendLine(); // Add an extra line between paragraphs
        }
        System.IO.File.Delete(tempFilePath); // Clean up the temporary file
        return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error processing document");
        return Json(new { success = false, message = "An error occurred while processing the document." });
    }
}
[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return Json(new { success = false, message = "No file uploaded." });
    }
    var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
    if (fileExtension != ".doc" && fileExtension != ".docx")
    {
        return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
    }
    try
    {
        var tempFilePath = Path.GetTempFileName();
        using (var stream = new FileStream(tempFilePath, FileMode.Create))
        {
            file.CopyTo(stream);
        }
        StringBuilder contentBuilder = new StringBuilder();
        WordDocument doc = new WordDocument(tempFilePath);
        foreach (Paragraph paragraph in doc.Paragraphs)
        {
            foreach (Text textRun in paragraph.Texts)
            {
                contentBuilder.AppendLine(textRun.Text);
            }
            contentBuilder.AppendLine(); // Add an extra line between paragraphs
        }
        System.IO.File.Delete(tempFilePath); // Clean up the temporary file
        return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error processing document");
        return Json(new { success = false, message = "An error occurred while processing the document." });
    }
}
<HttpPost>
Public Function UploadAndProcess(ByVal file As IFormFile) As IActionResult
	If file Is Nothing OrElse file.Length = 0 Then
		Return Json(New With {
			Key .success = False,
			Key .message = "No file uploaded."
		})
	End If
	Dim fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant()
	If fileExtension <> ".doc" AndAlso fileExtension <> ".docx" Then
		Return Json(New With {
			Key .success = False,
			Key .message = "Invalid file type. Please upload a .doc or .docx file."
		})
	End If
	Try
		Dim tempFilePath = Path.GetTempFileName()
		Using stream = New FileStream(tempFilePath, FileMode.Create)
			file.CopyTo(stream)
		End Using
		Dim contentBuilder As New StringBuilder()
		Dim doc As New WordDocument(tempFilePath)
		For Each paragraph As Paragraph In doc.Paragraphs
			For Each textRun As Text In paragraph.Texts
				contentBuilder.AppendLine(textRun.Text)
			Next textRun
			contentBuilder.AppendLine() ' Add an extra line between paragraphs
		Next paragraph
		System.IO.File.Delete(tempFilePath) ' Clean up the temporary file
		Return Json(New With {
			Key .success = True,
			Key .content = FormatContentAsHtml(contentBuilder.ToString())
		})
	Catch ex As Exception
		_logger.LogError(ex, "Error processing document")
		Return Json(New With {
			Key .success = False,
			Key .message = "An error occurred while processing the document."
		})
	End Try
End Function
VB   C#

This method performs the following tasks:

  1. Validates the uploaded file, ensuring it's in the correct file format (DOC or DOCX)
  2. Checks for the correct file extension
  3. Processes the document using the IronWord library
  4. Returns the formatted content as JSON

3.2.2 FormatContentAsHtml Method

This private method formats the extracted content into HTML:

private string FormatContentAsHtml(string content)
{
    var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
    var htmlBuilder = new StringBuilder();
    htmlBuilder.Append("<div class='document-content'>");
    foreach (var line in lines)
    {
        if (string.IsNullOrWhiteSpace(line))
        {
            htmlBuilder.Append("<p> </p>");
        }
        else
        {
            htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
        }
    }
    htmlBuilder.Append("</div>");
    return htmlBuilder.ToString();
}
private string FormatContentAsHtml(string content)
{
    var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
    var htmlBuilder = new StringBuilder();
    htmlBuilder.Append("<div class='document-content'>");
    foreach (var line in lines)
    {
        if (string.IsNullOrWhiteSpace(line))
        {
            htmlBuilder.Append("<p> </p>");
        }
        else
        {
            htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
        }
    }
    htmlBuilder.Append("</div>");
    return htmlBuilder.ToString();
}
Private Function FormatContentAsHtml(ByVal content As String) As String
	Dim lines = content.Split( { Environment.NewLine }, StringSplitOptions.None)
	Dim htmlBuilder = New StringBuilder()
	htmlBuilder.Append("<div class='document-content'>")
	For Each line In lines
		If String.IsNullOrWhiteSpace(line) Then
			htmlBuilder.Append("<p> </p>")
		Else
			htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>")
		End If
	Next line
	htmlBuilder.Append("</div>")
	Return htmlBuilder.ToString()
End Function
VB   C#

This method ensures the document content is properly formatted as HTML, with each line wrapped in paragraph tags and empty lines preserved.

3.3 Client-Side JavaScript

To handle the file upload and display the processed content, we use JavaScript:

uploadBtn.addEventListener('click', () => {
    const file = fileInput.files[0];
    if (!file) {
        alert('Please select a file first.');
        return;
    }
    const formData = new FormData();
    formData.append('file', file);
    uploadBtn.disabled = true;
    uploadBtn.textContent = 'Processing...';
    documentContent.innerHTML = 'Processing document...';
    fetch('/Home/UploadAndProcess', {
        method: 'POST',
        body: formData
    })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                documentContent.innerHTML = data.content;
            } else {
                documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
            }
        })
        .catch(error => {
            console.error('Error:', error);
            documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
        })
        .finally(() => {
            uploadBtn.disabled = false;
            uploadBtn.textContent = 'Upload and Process';
        });
});
uploadBtn.addEventListener('click', () => {
    const file = fileInput.files[0];
    if (!file) {
        alert('Please select a file first.');
        return;
    }
    const formData = new FormData();
    formData.append('file', file);
    uploadBtn.disabled = true;
    uploadBtn.textContent = 'Processing...';
    documentContent.innerHTML = 'Processing document...';
    fetch('/Home/UploadAndProcess', {
        method: 'POST',
        body: formData
    })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                documentContent.innerHTML = data.content;
            } else {
                documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
            }
        })
        .catch(error => {
            console.error('Error:', error);
            documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
        })
        .finally(() => {
            uploadBtn.disabled = false;
            uploadBtn.textContent = 'Upload and Process';
        });
});
uploadBtn.addEventListener( 'click', () =>
If True Then
	const file = fileInput.files(0)
	If Not file Then
		alert( 'Please select a file first.');
		Return
	End If
	const formData = New FormData()
	formData.append( 'file', file);
	uploadBtn.disabled = True
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'	uploadBtn.textContent = 'Processing...'; documentContent.innerHTML = 'Processing document...'; fetch('/Home/UploadAndProcess', { method: 'POST', body: formData }).@then(response => response.json()).@then(data => { if(data.success) { documentContent.innerHTML = data.content; } else { documentContent.innerHTML = `<p> @Error: ${data.message}</p>`; } }).catch(@error => { console.@error('@Error:', @error); documentContent.innerHTML = '<p> An @error occurred while processing the document.</p>'; }).finally(() => { uploadBtn.disabled = False; uploadBtn.textContent = 'Upload @and Process'; }); });
VB   C#

This JavaScript code handles the file upload process, sends the file to the server for processing, and updates the UI with the processed content or error messages.

3.4 Styling the User Interface

The application uses custom CSS to create an attractive and user-friendly interface.

<style>
    body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background-color: #f7f7f7;
        color: #333;
    }
    .container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
        padding-top: 0.5rem;
    }
    h1 {
        font-weight: 300;
        color: #2c3e50;
        text-align: center;
        margin-bottom: 1rem;
    }
    .lead {
        text-align: center;
        color: #7f8c8d;
        margin-bottom: 2rem;
    }
    .upload-area {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 2rem;
        text-align: center;
        margin-bottom: 2rem;
        transition: all 0.3s ease;
    }
        .upload-area:hover {
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
        }
    .file-icon {
        width: 64px;
        height: 64px;
        margin-bottom: 1rem;
        color: #3498db;
    }
    .choose-file {
        background-color: #ecf0f1;
        color: #2c3e50;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }
        .choose-file:hover {
            background-color: #d5dbdb;
        }
    .file-info {
        font-size: 0.9em;
        color: #95a5a6;
        margin-top: 0.5rem;
    }
    .upload-button {
        background-color: #3498db;
        color: white;
        border: none;
        padding: 0.75rem 1.5rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
        margin-top: 1rem;
    }
        .upload-button:hover {
            background-color: #2980b9;
        }
    .content-wrapper {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 1rem;
        margin-top: 2rem;
    }
    .content-area {
        max-height: 300px;
        overflow-y: auto;
        padding: 1rem;
        background-color: #f9f9f9;
        border-radius: 4px;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        font-size: 14px;
        line-height: 1.6;
    }
        .content-area::-webkit-scrollbar {
            width: 8px;
        }
        .content-area::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }
        .content-area::-webkit-scrollbar-thumb {
            background: #bdc3c7;
            border-radius: 4px;
        }
            .content-area::-webkit-scrollbar-thumb:hover {
                background: #95a5a6;
            }
    .document-content p {
        margin: 0 0 10px 0;
    }
</style>
<style>
    body {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        background-color: #f7f7f7;
        color: #333;
    }
    .container {
        max-width: 800px;
        margin: 0 auto;
        padding: 2rem;
        padding-top: 0.5rem;
    }
    h1 {
        font-weight: 300;
        color: #2c3e50;
        text-align: center;
        margin-bottom: 1rem;
    }
    .lead {
        text-align: center;
        color: #7f8c8d;
        margin-bottom: 2rem;
    }
    .upload-area {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 2rem;
        text-align: center;
        margin-bottom: 2rem;
        transition: all 0.3s ease;
    }
        .upload-area:hover {
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
        }
    .file-icon {
        width: 64px;
        height: 64px;
        margin-bottom: 1rem;
        color: #3498db;
    }
    .choose-file {
        background-color: #ecf0f1;
        color: #2c3e50;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
    }
        .choose-file:hover {
            background-color: #d5dbdb;
        }
    .file-info {
        font-size: 0.9em;
        color: #95a5a6;
        margin-top: 0.5rem;
    }
    .upload-button {
        background-color: #3498db;
        color: white;
        border: none;
        padding: 0.75rem 1.5rem;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s ease;
        margin-top: 1rem;
    }
        .upload-button:hover {
            background-color: #2980b9;
        }
    .content-wrapper {
        background-color: #ffffff;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 1rem;
        margin-top: 2rem;
    }
    .content-area {
        max-height: 300px;
        overflow-y: auto;
        padding: 1rem;
        background-color: #f9f9f9;
        border-radius: 4px;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        font-size: 14px;
        line-height: 1.6;
    }
        .content-area::-webkit-scrollbar {
            width: 8px;
        }
        .content-area::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }
        .content-area::-webkit-scrollbar-thumb {
            background: #bdc3c7;
            border-radius: 4px;
        }
            .content-area::-webkit-scrollbar-thumb:hover {
                background: #95a5a6;
            }
    .document-content p {
        margin: 0 0 10px 0;
    }
</style>
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'(Of style) body
'{
''INSTANT VB TODO TASK: The following line uses invalid syntax:
''		font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f7f7f7; color: #333; } .container { max-width: 800px; margin: 0 auto; padding: 2rem; padding-top: 0.5rem; } h1 { font-weight: 300; color: #2c3e50; text-align: center; margin-bottom: 1rem; } .lead { text-align: center; color: #7f8c8d; margin-bottom: 2rem; } .upload-area { background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 2rem; text-align: center; margin-bottom: 2rem; transition: all 0.3s ease; } .upload-area:hover { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); } .file-icon { width: 64px; height: 64px; margin-bottom: 1rem; color: #3498db; } .choose-file { background-color: #ecf0f1; color: #2c3e50; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease; } .choose-file:hover { background-color: #d5dbdb; } .file-info { font-size: 0.9em; color: #95a5a6; margin-top: 0.5rem; } .upload-button { background-color: #3498db; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; cursor: pointer; transition: background-color 0.3s ease; margin-top: 1rem; } .upload-button:hover { background-color: #2980b9; } .content-wrapper { background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 1rem; margin-top: 2rem; } .content-area { max-height: 300px; overflow-y: auto; padding: 1rem; background-color: #f9f9f9; border-radius: 4px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 14px; line-height: 1.6; } .content-area::-webkit-scrollbar { width: 8px; } .content-area::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; } .content-area::-webkit-scrollbar-thumb { background: #bdc3c7; border-radius: 4px; } .content-area::-webkit-scrollbar-thumb:hover { background: #95a5a6; } .document-content p { margin: 0 0 10px 0; } </style>
VB   C#

This CSS creates a clean, modern look with a light color scheme. The upload area features a white background with subtle shadow effects, while the content area has a scrollable design with a light grey background. Using border-radius and box-shadow properties adds depth and visual interest to the interface elements.

4. Exporting Word Documents

As we continue to enhance our Word Document Processor, let's add the ability to export documents. This feature will allow users to generate a new Word document from our application.

4.1 Updating the User Interface

First, we'll add an "Export" option to our navigation bar. Open the _Layout.cshtml file in the Views/Shared folder and locate the

Kannaopat Udonpant

Kannapat Udonpant

Software Engineer

 LinkedIn

Before becoming a Software Engineer, Kannapat completed a Environmental Resources PhD from Hokkaido University in Japan. While pursuing his degree, Kannapat also became a member of the Vehicle Robotics Laboratory, which is part of the Department of Bioproduction Engineering. In 2022, he leveraged his C# skills to join Iron Software's engineering team, where he focuses on IronPDF. Kannapat values his job because he learns directly from the developer who writes most of the code used in IronPDF. In addition to peer learning, Kannapat enjoys the social aspect of working at Iron Software. When he's not writing code or documentation, Kannapat can usually be found gaming on his PS5 or rewatching The Last of Us.
NEXT >
VS 2022 Programmatically Create New Word Documents (Tutorial)