通过多个工作表设置单元格值

问题描述 投票:0回答:1

我有一个我作为VSTO构建的股票代码,它可以获取价格,然后将其插入特定工作表中的单元格中。这些工作表通过用户按钮添加,添加新工作表,格式化,然后将其名称添加到“accountList”工作表(跟踪所有这些特殊工作表)。

问题是它只写入用户添加的最新工作表。以下是工作表循环期间发生的事情的片段。

foreach (Excel.Worksheet currentWorksheet in Globals.ThisAddIn.Application.Worksheets)
            {                    
                tickerRange = currentWorksheet.Range["A6:A1000", Type.Missing]; //location of ticker symbols

                //compare the current worksheet name to any of the names in the accountList
                if (Array.IndexOf(accountList.ToArray(), currentWorksheet.Name) >= 0) { 
                //for every row in the specified range
                foreach (Excel.Range row in tickerRange) //for every row inside the tickerRange variable
                {                        
                    try
                    {
                        quoteCell = row.Offset[0, 5]; //location where market price will be inserted
                        string currentStock = row.Value2; //set ticker Symbol equal to the cell of the range element

                        if (string.IsNullOrEmpty(currentStock) || currentStock.Trim().Length > 4) //if there is nothing in the cell or the length is more than 4 characters, don't call the fetchPrice.
                        {
                             badValue = true;
                        }//end if
                        else if (Regex.IsMatch(currentStock, "[ ]|[0-9]")) //if the cell has whitespace or numbers, don't call fetchPrice. This would result in bad output
                        {
                             badValue = true;
                        }
                        else
                        {
                            currentStock = currentStock.ToUpper();
                        }

                        if (!badValue) //if the dictionary contains the ticker symbol, no need to call fetchPrice again this loop, just get the value out of dictionary
                        {
                            price = tickerDictionary[currentStock];
                            quoteCell.Value2 = price;
                            //volumeCell.Value2 = (stockObject.minuteVolume / stockObject.currentVolume)*100;
                            //break;
                        }
                    } //end try
                    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException rbe) //i forget why i had to catch this in the first place. but it came up once, and now it's caught. so there's that. 
                    {
                        Console.WriteLine("Runtime Binder Exception caught");
                    }//end catch
                    catch (System.Runtime.InteropServices.COMException ce)
                    {
                        stopTicker();
                    }
                } //end 'row' foreach
            } //end 'sheet' foreach

在调试期间观察局部变量我可以看到accountList填充了正确的信息,并且foreach循环正在访问我的其他工作表,但quoteCell.Value2 = price不会更新除我最新之外的任何其他工作表的价格。

我在这里想念傻事吗?

c# excel vsto office-interop
1个回答
0
投票

我使用this link here发现了问题,因为它们的索引访问器不可靠,因此警告不要使用foreach而不是COM对象。

在切换了一些东西后,用好的循环替换了我的foreach,我正在做生意。这是更新的代码:

 Sheets worksheets = Globals.ThisAddIn.Application.ActiveWorkbook.Sheets;
            int wsCount = worksheets.Count;
            for (int w = 1; w <= wsCount; w++)
            {                    
                Worksheet currentWorksheet = worksheets.Item[w] as Worksheet;                       
                    string mysheet = currentWorksheet.Name;                    
                    tickerRange = null;
                    tickerRange = currentWorksheet.Range["A6:A1000", Type.Missing]; //location of ticker symbols
                    if (Array.IndexOf(accountList.ToArray(), mysheet) >= 0)
                    {
                        //for every row in the specified range
                        //foreach (Range row in currentWorksheet.Range["A6:A1000", Type.Missing]) //for every row inside the tickerRange variable
                        for (int r = 6; r <=1000; r++)
                        {
                            try
                            {
                                badValue = false;
                                Range row = null;
                                row = currentWorksheet.Range["A" + r];                                    
                                quoteCell = null;
                                //quoteCell = currentWorksheet.Range["A6:A1000", Type.Missing];
                                //quoteCell = quoteCell.Range[row.Offset[0, 5], Type.Missing];
                                quoteCell = row.Offset[0, 5]; //location where market price will be inserted
                                string currentStock = row.Value2; //set ticker Symbol equal to the cell of the range element                            
                                if (string.IsNullOrEmpty(currentStock) || currentStock.Trim().Length > 4) //if there is nothing in the cell or the length is more than 4 characters, don't call the fetchPrice.
                                {
                                    badValue = true;
                                }//end if
                                else if (Regex.IsMatch(currentStock, "[ ]|[0-9]")) //if the cell has whitespace or numbers, don't call fetchPrice. This would result in bad output
                                {
                                    badValue = true;
                                }
                                else
                                {
                                    currentStock = currentStock.ToUpper();
                                }

                                if (!badValue) //if the dictionary contains the ticker symbol, no need to call fetchPrice again this loop, just get the value out of dictionary
                                {
                                    price = tickerDictionary[currentStock];
                                    quoteCell.Value2 = price;
                                    //volumeCell.Value2 = (stockObject.minuteVolume / stockObject.currentVolume)*100;
                                    //break;
                                }
                            } //end try
                            catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException rbe) //i forget why i had to catch this in the first place. but it came up once, and now it's caught. so there's that. 
                            {
                                Console.WriteLine("Runtime Binder Exception caught");
                            }//end catch
                            catch (System.Runtime.InteropServices.COMException ce)
                            {
                                stopTicker();
                            }
                            /*if a KeyNotFound exception was thrown, it was because the user entered a new stock symbol while the loop was running, but
                            AFTER assemblePrice() was called. This results in the dictionary being asked for something it doesn't have. Just run assemblePrice() again. 
                            */
                            catch (System.Collections.Generic.KeyNotFoundException knfe) 
                            {                                
                            assemblePrice(); 
                            }
                        } //end for
                    }

                Console.WriteLine("For Loop Completed");
                Console.WriteLine("Sleep Started for " + restartTime + "seconds");
                //if the timerbox is empty, is set to 5 or less, or contains non-numeric characters
                if (string.IsNullOrEmpty(timerBox.Text) || Regex.Equals(timerBox.Text, "[0-5]") || Regex.IsMatch(timerBox.Text, "[^0-9]"))
                {
                    restartTime = 10;
                }//end else
                else
                {
                    restartTime = Convert.ToInt32(timerBox.Text); //restartTime gets the value after string contents of timerBox are cast to int.
                }//end else
            }//bigger for loop done
© www.soinside.com 2019 - 2024. All rights reserved.