3

We use an Excel sheet which contains some business logic (and so it is often edited by non-IT). Some C++ code is generated in VBA from the same sheet - silly, I know. I plan to write a bunch of unit tests against this worksheet, ensuring strict format for the benefit of all. For instance, things should be sorted alphabetically. I have not done this sort of work before; not even sure which library to use. To get my feet wet, I would like to find all cells which have font other than "automatic color, plain style, Arial, size 10" - e.g. red or bold or size 11, or ComicSans font. Then I want to check if those cells are "non-header" cells. The "header" cells are those which are part of known named ranges. For instance, if such cell does belong to a named range "XYZheaders", then it is Ok. If not, then I wish to report the coordinates of a cell (ideally as something human-readable like "D25" for every cell which has a problem, as well as indicate whether the problem is with color, font type, style, or size.

EDIT: I just put bounty on this question because I am looking for a complete C# sample. Please do ask questions if you think that my question is ambiguous.

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 の 4 つの参照を使用してビルドできます。

.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 ファイルの名前を想定しています。このファイルが開かれ、各セルがさまざまなフォント基準に対してテストされます。「non-default-font」を含むセルは、指定された範囲に対してテストされ、これらの範囲外にあるセルはコンソールに出力されます。

いつものように、エラー処理をプログラムに追加する必要がありますが、うまくいけば、これで作業を開始できます。

于 2010-07-24T12:08:52.103 に答える