Comment vérifier si une cellule non-tête dans le fichier Excel est en gras ou en italique
-
02-10-2019 - |
Question
Nous utilisons une feuille Excel qui contient une logique métier (et il est édité souvent par des non-IT). Certains code C généré en est de VBA à partir de la même feuille - stupide, je sais. Je prévois d'écrire un tas de tests unitaires contre cette feuille, assurant format strict au profit de tous. Par exemple, les choses devraient être classés par ordre alphabétique. Je ne l'ai pas fait ce genre de travail avant; même pas sûr d'utiliser la bibliothèque. Pour me mouiller les pieds, je voudrais trouver toutes les cellules qui ont la police autre que « automatique des couleurs, style simple, Arial, taille 10 » - par exemple rouge ou gras ou de la taille 11, ou la police Comic Sans. Ensuite, je veux vérifier si ces cellules sont des cellules « non-tête ». Les cellules « en-tête » sont ceux qui font partie des plages nommées connues. , Alors il est Ok Par exemple, si une telle cellule ne appartient à une plage nommée « XYZheaders ». Sinon, je voudrais signaler les coordonnées d'une cellule (idéalement comme quelque chose de lisible par l'homme comme « D25 » pour chaque cellule qui a un problème, ainsi que d'indiquer si le problème est avec la couleur, le type de police, le style ou la taille .
EDIT: Je prime vient de mettre sur cette question parce que je suis à la recherche d'un échantillon complet C #. S'il vous plaît ne poser des questions si vous pensez que ma question est ambiguë.
La solution
Voici ma solution. Je l'ai testé avec des fichiers Excel 2007 (.xlsx) de. Le programme peut être construit en utilisant VS 2010 (ciblage .NET 4) avec les quatre références suivantes: Microsoft.CSharp, Microsoft.Office.Interop.Excel, système et System.Core.
Utilisation de .NET 4 rend un peu plus facile de travailler avec Excel.
Quoi qu'il en soit, voici le code:
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));
}
}
}
Le programme prend le nom d'un fichier excel comme premier argument. Ce fichier est ouvert et chaque cellule est testée par rapport polices différentes critères. Les cellules avec « non-police par défaut » est soumis à l'essai nommé à distance, et ceux qui se situent en dehors de ces plages sont à la console.
Comme d'habitude certains ErrorHandling devrait être ajouté au programme -. Mais nous espérons que cela devrait vous aider à démarrer
Autres conseils
Cela devrait faire l'affaire, profiter. Gardez à l'esprit que la mise en nouveaux noms Range ne déclenche pas un recalcul d'une cellule contenant cette fonction (si frappé F9 après la création d'un nom de plage).
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