使用代码在Excel的名称pipe理器中对命名范围进行sorting

我使用VSTO从Excel电子表格中获得命名范围列表:

public List<Name> GetNamedRanges(Workbook activeWorkbook) { List<Name> namedRanges = new List<Name>(); Name name; for (int i = 0; i < activeWorkbook.Names.Count; i++) { name = activeWorkbook.Names.Item(i + 1); if (!name.Value.Contains("#REF")) { namedRanges.Add(name); } } return namedRanges; } 

这会以奇怪的顺序返回名称:

在这里输入图像说明

有没有人有一个简单的方法按列顺序对名称范围进行sorting。 例如:

工作表Sheet1 = $ A $ 9:!$ B $ 172
工作表Sheet1 = $ C $ 9:$!d $ 172
工作表Sheet1 = $ E $ 41!$ F $ 172

http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting获取代码,然后对其进行修改,使其按string长度(按数字拆分后)进行sorting,然后进行自然sorting&#x3002; 限制是,如果你有不同的名字表,你的表也将按string长度sorting,而不是asininumerical。

 public class ExcelNameComparer<T> : IComparer<IEnumerable<T>> { /// <summary> /// Create a sequence comparer using the default comparer for T. /// </summary> public ExcelNameComparer() { comp = Comparer<T>.Default; } /// <summary> /// Create a sequence comparer, using the specified item comparer /// for T. /// </summary> /// <param name="comparer">Comparer for comparing each pair of /// items from the sequences.</param> public ExcelNameComparer(IComparer<T> comparer) { comp = comparer; } /// <summary> /// Object used for comparing each element. /// </summary> private IComparer<T> comp; /// <summary> /// Compare two sequences of T. /// </summary> /// <param name="x">First sequence.</param> /// <param name="y">Second sequence.</param> public int Compare(IEnumerable<T> x, IEnumerable<T> y) { using (IEnumerator<T> leftIt = x.GetEnumerator()) using (IEnumerator<T> rightIt = y.GetEnumerator()) { while (true) { bool left = leftIt.MoveNext(); bool right = rightIt.MoveNext(); if (!(left || right)) return 0; if (!left) return -1; if (!right) return 1; int lengthResult = leftIt.Current.ToString().Length.CompareTo(rightIt.Current.ToString().Length); if (lengthResult != 0) return lengthResult; int itemResult = comp.Compare(leftIt.Current, rightIt.Current); if (itemResult != 0) return itemResult; } } } Func<string, object> convert = str => { try { return int.Parse(str); } catch { return str; } }; 

现在运行实际的sorting:

  var lst = new List<string> { "Sheet1!$A$9:$B$172", "Sheet1!$AY$77:$AZ$172", "Sheet1!$E$41:$F$172", "Sheet1!$A$10:$B$172", "Sheet1!$A$1:$B$172" }; var sorted = lst.OrderBy( str => Regex.Split(str.Replace(" ", ""), "([0-9]+)").Select(convert), new ExcelNameComparer<object>()); foreach (var sort in sorted) { System.Diagnostics.Debug.Print(sort); } 

产量:

工作表Sheet1 $ A $ 1:$ B $ 172
工作表Sheet1!$ A $ 9:!$ B $ 172
工作表Sheet1 $ A $ 10:$ B $ 172
!工作表Sheet1 $ E $ 41:$ F $ 172
!工作表Sheet1 $ AY $ 77:$ AZ $ 172

在Excel中对它们进行sorting,然后再次读入工作簿。 (是一个简单的方法。)

我只是通过删除数字,然后按长度sorting,然后按字母sorting,它非常混乱,但是做的工作:

 static public List<Name> GetNamedRangesInOrder(Workbook activeWorkbook) { List<Name> namedRanges = GetNamedRanges(activeWorkbook); List<string> lstStringNameRanges = new List<string>(); foreach (var item in namedRanges) { lstStringNameRanges.Add(RemoveDigits(item.RefersTo.ToString())); } IEnumerable<string> results = SortByLengthAndName(lstStringNameRanges); List<Name> sortedNamedRanges = new List<Name>(); foreach (var item in results) { int index = -1; for (int i=0; i < namedRanges.Count; i++) { if (RemoveDigits(namedRanges[i].RefersTo.ToString()) == item.ToString()) { index = i; break; } } sortedNamedRanges.Add(namedRanges[index]); } return sortedNamedRanges; } static public IEnumerable<string> SortByLengthAndName(IEnumerable<string> e) { IEnumerable<string> query = e.OrderBy(x => x.Length).ThenBy(x => x).ToList(); return query; } static public string RemoveDigits(string e) { string str = new string((from c in e where char.IsLetter(c) || char.IsSymbol(c) select c).ToArray()); return str; }