2

我正在编写一个脚本来检查一堆 Excel 电子表格中的某些值,我最终得到的代码如下所示:

    public bool checkContents(Excel._Worksheet sht, string address, string cellValue)
    {
        Excel.Range tempRange = sht.get_Range(address);
        return Convert.ToString(tempRange.Value) == cellValue;
    }

    public string getVersion(Excel._Worksheet sht)
    {
        if (checkContents(sht,"a4","Changes for Version 24"))
        {
            return "24";
        }
        else if (checkContents(sht,"a1","Changes for Version 23 (Official)"))
        {
            return "23";
        }
        else if (checkContents(sht,"a2","Changes for Version 22"))
        {
            return "22";
        }


       //and so on for another 10 if-else blocks 
    }

我知道对于给定的工作表,只有一个if陈述是正确的。

if除了长序列的s之外,还有更简洁的方法来编写这个函数吗?

4

6 回答 6

4

你可以尝试这样的事情(未经测试,所以可能有一些语法错误)

    private class VersionSpec
    {
        public string Address { get; private set; }
        public string CellValue { get; private set; }
        public string Version { get; private set; }

        public VersionSpec (string address, string cellValue, string version)
        {
            Address = address;
            CellValue = cellValue;
            Version = version;
        }
    }

    public string getVersion(Excel._Worksheet sht)
    {
        VersionSpec[] versionSpecs = new []
        {
            new VersionSpec("a4", "Changes for Version 24", "24"),
            new VersionSpec("a1", "Changes for Version 23 (Official)", "23"),
            new VersionSpec("a2", "Changes for Version 22", "22"),
            // other versions...
        }

        foreach(VersionSpec versionSpec in versionSpecs)
        {
            if(checkContents(sht, versionSpec.Address, versionSpec.CellValue))
            {
                return versionSpec.Version;
            }
        } 
    }
于 2012-11-20T00:00:22.313 回答
1

由于您的单元格值似乎不一致,您可以将所有参数放入自定义对象列表中,类似于以下内容。

public class Version
{
    public string CellAddress { get; set; }
    public string CellValue { get; set; }
    public string ReturnValue { get; set; }
}

Then load up a List<Version> with your various versions. Afterwards you can use a foreach loop on the list and react when you get a hit with one of them.

于 2012-11-20T00:01:03.077 回答
0

使用 .Net 4.0 Excel Interop,您不需要使用下划线 _Types,而是使用方括号。

public bool checkContentsStartsWith(Worksheet sht, string address, string cellValue)
{
   Range tempRange = sht.Range[address];
  return cellValue.StartsWith(tempRange.Value2);
}

public string getVersion(Worksheet sht)
{
    for (int j = 1; j < 4;j++)
    {
        for (int i = 24; i > 0; i--)
        {
            if (checkContentsStartsWith(sht, "A" + j.ToString(), "Changes for Version " + i))
            {
                return i;
            }
        }
    }
}
于 2012-11-19T23:57:13.763 回答
0

If the rest of your if-blocks are the same structure as the sample posted, there's a clear pattern here; couldn't you check a larger range (e.g; "a1:a4") for the existence of the string "Changes for Version", return that string, and parse out the integer you want to return. You should be able to knock that down to 2-3 LOC if you adjust your thinking a little?

Some code to elucidate;

    public static string getVersion(Worksheet sht)
    {
        Range range = sht.Range["A1:A10"];
        foreach (Range c in range.Cells)
        {
            if (null == c.Value2) continue;
            string val = c.Value.ToString();
            if (val.Contains("Changes for Version "))
            {
                int startIndex = ("Changes for Version ").Length;
                return val.Substring(startIndex, 2).Trim(); 
            }
        }

        return null;
    }
于 2012-11-20T00:05:41.650 回答
0

I have another answer:

using (var usedRange = sheet.UsedRange.WithComCleanup())
{
    string firstAddress = string.Empty;
    string nextAddress = string.Empty;
    using (var firstCell = usedRange.Resource.Find("Changes for Version", LookIn: XlFindLookIn.xlValues).WithComCleanup())
    {    
        if (firstCell.Resource != null)
        {
            firstAddress = firstCell.Resource.Address;
            AppendListOfVersion(sheet.Name, firstCell.Resource);
            nextAddress = firstAddress;
        }
    }
}
if (firstAddress != "") // the first Find attempt was successful, so keep looking (FindNext)
{
    var keepLooking = true;
    while (keepLooking)
    {
        using (var prevCellToFindNextFrom = sheet.Range[nextAddress].WithComCleanup())
        using (var nextCell = usedRange.Resource.FindNext(prevCellToFindNextFrom.Resource).WithComCleanup())
        {
            if (nextCell.Resource == null)
                keepLooking = false;
            else
            {
                nextAddress = nextCell.Resource.Address;
                if (nextAddress == firstAddress)
                    keepLooking = false;
                else
                    AppendListOfVersion(sheet.Name, nextCell.Resource);
            }
        }
    }
}

You can learn about the WithComCleanUp() here: http://jake.ginnivan.net/vsto-com-interop

于 2012-11-20T00:13:11.913 回答
0

Here's a couple of options:

    public string getVersion(Excel._Worksheet sht)
    {
        if (checkContents(sht, "a4", "Changes for Version 24"))
            return "24";
        if (checkContents(sht, "a1", "Changes for Version 23 (Official)"))
            return "23";
        if (checkContents(sht, "a2", "Changes for Version 22"))
            return "22";
        //and so on for another 10 if-else blocks 
    }


    public string getVersion(Excel._Worksheet sht)
    {
        string[][] values = new string[3][]{
                            new string[3]{"a4","Changes for Version 24","24"}
                            ,new string[3]{"a1", "Changes for Version 23 (Official)","23"}
                            ,new string[3]{"a2", "Changes for Version 22","22"}
                          };
        foreach (string[] strings in values)
        {
            if (checkContents(sht, strings[0], strings[1])) return strings[2];
        }
        return null; //or throw not found error 
    }
于 2012-11-20T00:21:35.747 回答