我使用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;
}
这会以奇怪的顺序返回名称:
有没有人有一种简单的方法来按列顺序对名称范围进行排序。例如:
= Sheet 1中$ A $ 9:!$ B $ 172
工作表Sheet1 = $ C $ 9:$!d $ 172
= Sheet1!$ E $ 41:$ F $ 172
答案 0 :(得分:1)
从http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting获取代码并对其进行修改,使其按字符串长度排序(按数字拆分后),然后按自然顺序排序。限制是,如果您有不同名称的工作表,您的工作表也将按字符串长度排序,而不是asciinumerical。
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; }
};
现在运行实际排序:
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!$ A $ 77:$ AZ $ 172
答案 1 :(得分:0)
在Excel中对它们进行排序,然后再次阅读工作簿。 (这是一种简单的方法。)
答案 2 :(得分:0)
我只是通过删除数字,然后按长度排序然后按字母顺序排序,它非常混乱但是完成了工作:
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;
}