3

我们使用包含一些业务逻辑的 Excel 表(因此通常由非 IT 人员编辑)。一些 C++ 代码是在 VBA 中从同一张表中生成的——我知道这很傻。我计划针对这个工作表编写一堆单元测试,确保严格的格式以造福所有人。例如,事物应该按字母顺序排序。我以前没有做过这种工作;甚至不确定要使用哪个库。为了弄湿我的脚,我想找到所有具有“自动颜色、纯样式、Arial、10 号”以外的字体的单元格——例如红色或粗体或 11 号或 ComicSans 字体。然后我想检查这些单元格是否是“非标题”单元格。“标题”单元格是已知命名范围的一部分。例如,如果这样的单元格确实属于命名范围“XYZheaders”,那么就可以了。如果不,

编辑:我只是悬赏这个问题,因为我正在寻找一个完整的 C# 示例。如果您认为我的问题模棱两可,请务必提出问题。

4

2 回答 2

3

这应该可以解决问题,享受。请记住,放入新的范围名称不会触发包含此函数的单元格的重新计算(因此F9在创建范围名称后点击)。

Option Explicit

Public Function IsDataCellBoldOrItalic() As Boolean
    Dim rngName As Name
    Dim intersectRange As Name

    For Each rngName In ActiveWorkbook.Names
        If Not Intersect(rngName.RefersToRange, Application.ThisCell) Is Nothing Then
            IsDataCellBoldOrItalic = False
            Exit Function
        End If
    Next

    ''# Now we know we are not in a "header" cell
    IsDataCellBoldOrItalic = Application.ThisCell.Font.Bold Or Application.ThisCell.Font.Italic

End Function
于 2010-07-06T21:10:14.763 回答
3

这是我的解决方案。我已经用一些 Excel 2007 文件 (.xlsx) 对其进行了测试。该程序可以使用 VS 2010(针对 .NET 4)构建,具有以下四个参考:Microsoft.CSharp、Microsoft.Office.Interop.Excel、System 和 System.Core。

使用 .NET 4 可以更轻松地使用 Excel。

无论如何,这是代码:

using System;
using System.Collections.Generic;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;

namespace ExcelTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Excel.Application excelapplication = null;
            Excel.Workbook workbook = null;

            try
            {
                excelapplication = new Excel.Application();
                workbook = excelapplication.Workbooks.Open(args[0]);
                var errors = new Dictionary<string, List<string>>();
                foreach (Excel.Worksheet sheet in workbook.Sheets)
                {
                    int rowCount = sheet.UsedRange.Cells.Rows.Count;
                    int colCount = sheet.UsedRange.Cells.Columns.Count;
                    var usedCells = sheet.UsedRange.Cells;

                    for (int i = 1; i <= rowCount; i++)
                    {
                        for (int j = 1; j <= colCount; j++)
                        {
                            Excel.Range range = usedCells[i, j];
                            List<string> cellErrors;
                            if (HasNonDefaultFont(range, out cellErrors))
                            {
                                if (!IsHeaderCell(workbook, range))
                                {
                                    string cellDisplayTitle = String.Format("{0}!{1}", sheet.Name, range.Address);
                                    errors[cellDisplayTitle] = cellErrors;
                                }
                            }
                        }
                    }
                }
                ReportErrors(errors);
            }
            finally
            {
                if (workbook != null)
                    workbook.Close();
                if (excelapplication != null)
                    excelapplication.Quit();
            }
        }

        static bool HasNonDefaultFont(Excel.Range range, out List<string> differences)
        {
            differences = new List<string>();

            if (range.Font.Color != 0.0)
                differences.Add("Has font-color");

            if (range.Font.Bold)
                differences.Add("Is bold");

            if (range.Font.Italic)
                differences.Add("Is italic");

            if (range.Font.Underline != (int)Microsoft.Office.Interop.Excel.XlUnderlineStyle.xlUnderlineStyleNone)
                differences.Add("Is underline");

            if (range.Font.Strikethrough)
                differences.Add("Is strikethrough");

            if (range.Font.Name != "Arial")
                differences.Add(String.Format("Font is {0}", range.Font.Name));

            if (range.Font.Size != 10)
                differences.Add(String.Format("Font size is {0}", range.Font.Size));

            return differences.Count != 0;
        }

        static bool IsHeaderCell(Excel.Workbook workbook, Excel.Range range)
        {
            // Look through workbook names:
            foreach (Excel.Name namedRange in workbook.Names)
            {
                if (range.Parent == namedRange.RefersToRange.Parent && range.Application.Intersect(range, namedRange.RefersToRange) != null)
                    return true;
            }

            // Look through worksheet-names.
            foreach (Excel.Name namedRange in range.Worksheet.Names)
            {
                if (range.Parent == namedRange.RefersToRange.Parent && range.Worksheet.Application.Intersect(range, namedRange.RefersToRange) != null)
                    return true;
            }
            return false;
        }

        static void ReportErrors(Dictionary<string, List<string>> errors)
        {
            if (errors.Count > 0)
            {
                Console.WriteLine("Found the following errors:");
                Console.WriteLine("---------------------------------");
                Console.WriteLine("{0,-15} | Error", "Cell");
                Console.WriteLine("---------------------------------");
            }

            foreach (KeyValuePair<string, List<string>> kv in errors)
                Console.WriteLine("{0,-15} | {1}", kv.Key, kv.Value.Aggregate((e, s) => e + ", " + s));
        }
    }
}

该程序假定一个 excel 文件的名称作为它的第一个参数。打开此文件,并针对不同的字体标准测试每个单元格。具有“非默认字体”的单元格针对命名范围进行测试,超出这些范围的单元格将输出到控制台。

像往常一样,应该在程序中添加一些错误处理——但希望这能让你开始。

于 2010-07-24T12:08:52.103 回答