使用IRONWORD

ASP .NET Core 匯入與匯出 Word 文件

發佈 2024年12月16日
分享:

介紹

本指南探討如何導入現有的Word文件、顯示其內容,並使用IronWord從頭開始創建文件。IronWord 函式庫. 在本教程結束時,您將創建一個ASP.NET Core可以實現以下功能的網路應用程式:

  1. 上傳並閱讀 Word 文件

  2. 在文本框中顯示這些文件的內容

  3. 匯出 Docx 文件

    此專案非常適合需要將 Word 文件處理整合到其網頁應用程式中的開發人員,無論是用於文件管理系統、報告生成器,或是任何其他涉及 Microsoft Word 文件的場景。

先決條件

要跟隨本教程,您應該具備:

  • C#和ASP.NET Core的基本知識
  • 安裝 Visual Studio 2019 或更高版本(或者,您可以使用帶有C#擴展的Visual Studio Code)
  • .NET Core SDK 3.1 或更高版本

    如果您不是這些技術的專家,也不用擔心——我們會指導您完成每個步驟。!

什麼是IronWord?

IronWord是一個 .NET 資料庫,允許開發人員以程式化方式讀取、操作和建立 Microsoft Word 文件。 它提供了高級 API,簡化了處理 Word 文件的過程,使其成為我們項目的極佳選擇。

IronWord 的一些主要功能包括:

  • 閱讀和编写各种 Word 格式 (DOCX、DOC 等。)
  • 操作文件內容及結構
  • 格式化文字和段落
  • 處理表格、圖像和其他文檔元素
  • 文件的郵件合併過程
  • 輕鬆地將 Word 文件轉換為 PDF 文件,這樣您就可以將最終的 Word 文件製作成易於共享的 PDF 文件。

    現在我們對我們要構建的內容和將使用的工具有了一個概覽,讓我們開始著手設置我們的專案。!

2. 設置專案

在本節中,我們將創建一個新的 ASP.NET Core 專案並安裝必要的套件以使用 IronWord。

2.1 建立新的 ASP.NET Core 專案

  1. 打開 Visual Studio 2019 或更高版本。

  2. 點擊「創建新專案」。

    1. 搜索「ASP.NET Core Web Application」並選擇它。

  3. 點擊「下一步」。

  4. 將您的專案命名為 "WordDocumentProcessor"(或任何您喜歡的名稱).

  5. 選擇 .NET Framework 和項目位置,然後點擊「建立」。

2.2 安裝 IronWord NuGet 套件

現在我們已經設置好項目,讓我們添加IronWord庫:

  1. 在方案總管中右鍵點擊你的專案。

  2. 選擇「管理 NuGet 套件」。

    1. 在「瀏覽」標籤中,搜索「IronWord」。

  3. 查找官方的IronWord套件。

  4. 點擊「安裝」將其添加到您的專案中。

2.3 更新現有的控制器和視圖

讓我們更新現有的結構以整合文件處理功能:

  1. 我們將使用控制器資料夾中的現有 HomeController.cs 來處理我們的文件處理邏輯。

  2. 我們將更新 Views/Home 資料夾中的現有 Index.cshtml 視圖,以納入文件上傳和顯示功能。

    現在我們已經設置好項目並安裝了IronWord套件,準備開始實施文件匯入和導出功能。 我們將在 HomeController 中新增方法並修改 Index 視圖來處理這些功能。 在下一節中,我們將專注於匯入 Word 文件並顯示其內容,利用我們現有的控制器和視圖結構。 我們也可以添加郵件合併功能,但本文將重點放在匯入和匯出文件上。

3. 匯入 Word 文件

在本節中,我們將探討如何在 ASP.NET MVC 應用程式中實現導入和處理 Word 文件的功能。 我們將涵蓋使用者介面設計和後端控制器邏輯。

3.1 使用者介面設計

匯入 Word 文件的使用者介面設計得直觀且視覺上具有吸引力。 讓我們分解 UI 的關鍵組成部分:

3.1.1 上傳區域

上傳區域是介面的焦點,邀請用戶選擇並上傳他們的 Word 文件。 以下是結構說明:

<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>
$vbLabelText   $csharpLabel

此代碼創建了一個視覺上吸引人的上傳區域,具有文件圖標、隱藏的文件輸入,以及充當文件選擇按鈕的樣式標籤。 它還包括有關可接受文件類型的信息以及一個用於啟動上傳和處理的按鈕。

3.1.2 內容顯示區域

處理完文件後,其內容將顯示在專用區域中:

<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>
$vbLabelText   $csharpLabel

此區域提供了一個可滾動的區域來顯示處理過的文件內容。

3.2 控制器實現

HomeController 負責處理匯入和處理 Word 文件的伺服器端邏輯。 我們來檢視主要的方法:

3.2.1 UploadAndProcess 方法

此方法負責處理文件上傳和處理:

[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 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
$vbLabelText   $csharpLabel

此方法執行以下任務:

  1. 驗證上傳的檔案,確保其為正確的檔案格式。(DOC 或 DOCX)

  2. 檢查正確的檔案擴展名

  3. 使用IronWord庫處理文件

  4. 將格式化內容作為 JSON 返回

3.2.2 FormatContentAsHtml 方法

此私有方法將提取的內容格式化為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
$vbLabelText   $csharpLabel

此方法確保文件內容正確格式化為HTML,每行都用段落標籤包裹,並保留空行。

3.3 客戶端 JavaScript

為了處理文件上傳並顯示處理後的內容,我們使用 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'; }); });
$vbLabelText   $csharpLabel

此 JavaScript 程式碼處理檔案上傳過程,將檔案傳送到伺服器進行處理,並使用處理過的內容或錯誤訊息更新使用者介面。

3.4 樣式化使用者介面

該應用程式使用自訂 CSS 來創建一個吸引人且使用者友好的介面。

<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>
$vbLabelText   $csharpLabel

這個 CSS 創建了一個乾淨、現代的外觀,具有輕盈的色彩方案。 上傳區域具有白色背景和微妙的陰影效果,而內容區域則設計為可捲動、淺灰色背景。 使用 border-radius 和 box-shadow 屬性可以為介面元素添加深度和視覺趣味。

4. 匯出 Word 文件

隨著我們不斷改進我們的文字文件處理器,讓我們新增文件匯出的功能。 此功能將允許用戶從我們的應用程式生成新的 Word 文件。

4.1 更新使用者介面

首先,我們將在導航欄中添加一個「匯出」選項。 在 Views/Shared 資料夾中打開 _Layout.cshtml 文件,然後找到

里根普恩

里根普恩

軟體工程師

 LinkedIn

Regan 畢業於雷丁大學,擁有電子工程學士學位。在加入 Iron Software 之前,他的工作角色讓他專注於單一任務;而他在 Iron Software 工作中最喜歡的是他所能承擔的工作範圍,無論是增加銷售價值、技術支持、產品開發或市場營銷。他喜歡了解開發人員如何使用 Iron Software 庫,並利用這些知識不斷改進文檔和開發產品。
下一個 >
VS 2022 程式化建立新的 Word 文件(教程)