C ++到VBA(Excel)

所以,基本上,在Excel中,我有4列的数据(所有的string),我想处理,并希望在另一列中的结果,像这样(从来不知道方括号,他们只是表示单元格):

Line Column1 Column2 Column3 Column4 Result 1: [a] [b] [k] [YES] [NO] 2: [a] [c] [l] [YES] [NO] 3: [b] [e] [] [YES] [NO] 4: [c] [e] [f] [NO] [NO] 5: [d] [h] [b] [NO] [NO] 6: [d] [] [w] [NO] [NO] 7: [e] [] [] [YES] [NO] 8: [j] [m] [] [YES] [YES] 9: [j] [] [] [YES] [YES] 10: [] [] [] [YES] [YES] 

我想要数据通过的过程是这样的:

假设CheckingLine是我当前想要计算Result的值的那一行,CurrentLine是我用来计算给定时刻Result值的任何Line(除了CheckingLine)。

  1. 如果Column4 [CheckingLine]是“NO”,结果是“NO”(足够简单,不需要帮助)。
    1. 例如:CheckingLine = 1 – > Column4 [1] =“NO” – > Result =“NO”;
  2. 否则,我想确保所有与CheckingLine(1到3之间的任何列)共享同一个值的行也将Column4设置为“YES”(即使没有使用VBA,这样做也会很简单 – 事实上,我已经开始通过简单的Excel来实现,并意识到这不是我想要的) – 如果发生这种情况,结果是“是”;
    1. 例如:CheckingLine = 8 – >只有共享值是“j” – > CurrentLine = 9 – > Column4 [9] =“YES” – > Result =“YES”;
    2. 这是棘手的部分:如果其中一行有任何值(再次,在1和3之间的任何列),不与CheckingLine共享,我想要做整个过程(从1重新启动),但检查CurrentLine而不是。
      1. 示例:CheckingLine = 2,“a”与第1行共享,c与第4行共享 – > CurrentLine = 1 – > Column4 [1] =“YES”,但“b”和“k”不与“CheckingLine”共享 – > CheckingLine'= 1 – >“b”与第5行共享 – > Column4 [5] =“NO” – > Result =“NO”;

我已经编写了相应的C ++代码(可以工作)(也可以是其他语言,C ++就是我目前使用的代码)(并且代码没有以任何方式进行优化,因为它的目的是对其function可能是AS CLEAR)(上表是运行它的实际结果):

 #include <iostream> #include <string> #include <vector> std::vector<std::string> column1, column2, column3, column4, contentVector; unsigned int location, columnsSize; void InsertInVector(std::string Content) { if(Content == "") { return; } for(unsigned int i = 0; i < contentVector.size(); i++) { if(contentVector[i] == Content) { return; } } contentVector.push_back(Content); } std::string VerifyCurrentVector(unsigned int Start) { std::string result = ""; if(contentVector.size() == 0) { result = "YES"; } else { unsigned int nextStart = contentVector.size(); for(unsigned int i = 0; i < columnsSize; i++) { if(i != location) { for(unsigned int j = Start; j < nextStart; j++) { if(column1[i] == contentVector[j]) { InsertInVector(column2[i]); InsertInVector(column3[i]); } else if(column2[i] == contentVector[j]) { InsertInVector(column1[i]); InsertInVector(column3[i]); } else if(column3[i] == contentVector[j]) { InsertInVector(column1[i]); InsertInVector(column2[i]); } } } } if(nextStart == contentVector.size()) { for(unsigned int i = 0; i < columnsSize; i++) { if(i != location) { for(unsigned int j = 0; j < nextStart; j++) { if(column1[i] == contentVector[j] || column2[i] == contentVector[j] || column3[i] == contentVector[j]) { if(column4[i] == "NO") { result = "NO"; return result; } } } } } result = "YES"; } else { result = VerifyCurrentVector(nextStart); } } return result; } std::string VerifyCell(unsigned int Location) { std::string result = ""; location = Location - 1; if(column4.size() < Location) { result = "Error"; } else if(column4[location] == "NO") { result = "NO"; } else { contentVector.clear(); InsertInVector(column1[location]); InsertInVector(column2[location]); InsertInVector(column3[location]); result = VerifyCurrentVector(0); } return result; } void SetUpColumns(std::vector<std::string> &Column1, std::vector<std::string> &Column2, std::vector<std::string> &Column3, std::vector<std::string> &Column4) { if(Column4.size() > Column1.size()) { for(unsigned int i = Column1.size(); i < Column4.size(); i++) { Column1.push_back(""); } } if(Column4.size() > Column2.size()) { for(unsigned int i = Column2.size(); i < Column4.size(); i++) { Column2.push_back(""); } } if(Column4.size() > Column3.size()) { for(unsigned int i = Column3.size(); i < Column4.size(); i++) { Column3.push_back(""); } } column1 = Column1; column2 = Column2; column3 = Column3; column4 = Column4; columnsSize = Column4.size(); } int main() { std::vector<std::string> Column1, Column2, Column3, Column4; Column1.push_back("a"); Column1.push_back("a"); Column1.push_back("b"); Column1.push_back("c"); Column1.push_back("d"); Column1.push_back("d"); Column1.push_back("e"); Column1.push_back("j"); Column1.push_back("j"); Column2.push_back("b"); Column2.push_back("c"); Column2.push_back("e"); Column2.push_back("e"); Column2.push_back("h"); Column2.push_back(""); Column2.push_back(""); Column2.push_back("m"); Column3.push_back("k"); Column3.push_back("l"); Column3.push_back(""); Column3.push_back("f"); Column3.push_back("b"); Column3.push_back("w"); Column4.push_back("YES"); Column4.push_back("YES"); Column4.push_back("YES"); Column4.push_back("NO"); Column4.push_back("NO"); Column4.push_back("NO"); Column4.push_back("YES"); Column4.push_back("YES"); Column4.push_back("YES"); Column4.push_back("YES"); SetUpColumns(Column1, Column2, Column3, Column4); std::cout << "Line\t" << "Column1\t" << "Column2\t" << "Column3\t" << "Column4\t" << std::endl; for(unsigned int i = 0; i < Column4.size(); i++) { std::cout << i + 1 << ":\t" << "[" << column1[i] << "]\t[" << column2[i] << "]\t[" << column3[i] << "]\t[" << column4[i] << "]\t[" << VerifyCell(i + 1) << "]" << std::endl; } return 0; } 

所以经过这个漫长的解释,我想知道的是这样的:

  • 有没有办法在Excel的VBA(甚至更好,在没有VBA的普通Excel中)做到这一点?
  • 如果没有,我怎么能得到我的代码(我可以很容易地翻译成另一种C语言和/或优化)从Excel中获取数据并将结果传递给Excel?

有没有办法在Excel的VBA中做到这一点?

是的,你一定可以用VBA来做这件事,它是一个完整而强大的编程语言

(甚至更好,在没有VBA的普通Excel中)?

不。 没有任何VBA代码,计算似乎太复杂,不适合使用Excel公式。

如果没有,我怎么能得到我的代码(我可以很容易地翻译成另一种C语言和/或优化)从Excel中获取数据并将结果传递给Excel?

您可以通过多种方式从C ++访问Excel。 使用ATL就是其中之一。 另一个更简单的方法是导入/导出CSV格式的Excel文件,这很容易从C ++parsing和写入。 还要考虑C#,它具有完整的COM互操作性来访问办公室组件。

好吧,如果你喜欢“匆匆匆匆的代码”,那么你会爱上VBA,下次请试着问一个更具体的问题。 基于代码和注释@MikeAscended你是一个相对较好的程序员,掌握函数/recursion,variables/参数,条件,循环,数据结构等。Re:“我一生只碰过一次VBA,跑过远离它“我的意图是让你开始,给你语法不一定是一个工作的解决scheme。 我很高兴回答您可能会继续的任何进一步的具体问题。

在策略方面 ,我推荐在Excel中易于使用的纯VBA。 显然你的问题可以通过许多方式来解决,包括公式,但是VBA是一个强大的工具,任何程序员都可以从中受益。

代码方面 ,要从Excel中按[Alt-F11]开始访问编辑器,或者从devise模式插入并双击一个ActiveXbutton。 要运行macros按[Alt-F8],或在VBA中单击绿色播放button。

最后一个注意,如果你想在Excel中的第1列的行号,那么你的将成为第2-5列或BF。 我假设你将在Excel中使用行号,以便列1是A,但行1仍然有标题,所以你正在盯着第2行的数据。

 sub processResults_Col5() ' Run This Script as Main() dim rowCount as long, i as long 'rowCount = columnsSize with sheets(1) .Range("A1:D1") = Array("a", "b", "k", "YES") ' finish init here ' SetUpColumns not necessary in excel if .cells(2,1).value <> "" then 'do not use .end(xldown) if data is missing rowCount = .cells(1,1).end(xldown).row for i = 1 to rowCount .cells(i,5) = verifyCell(i + 1, rowCount) next i endif 'space will be added :p end with end sub function verifyCell(rowLocation as long, size as long, optional wSh as excel.worksheet) as string ' the rest should be easy for you to figure out based on C-code with wSh if wsh is nothing then set wsh = activesheet 'let VBA capitalize stuff so you know you typed it correctly if size < rowlocation then verifyCell = "Error" 'the function name is the return value 'msgbox "Error" ' you can uncomment this line to see error elseif cells(rowLocation, 4).value = "NO" then cells(rowLocation, 5) = "NO" 'set result else call InsertInVector(rowLocation) 'CheckingLine ' edit the current rowLocation with for loops verifyCell = VerifyCurrentVector(0) 'whatever you're doing here endif end with end function sub InsertInVector() end sub sub VerifyCurrentVector() 'function returns a value end sub 

一些技巧:

  1. 一般来说,评论你的代码!
  2. 通常,variables和对象名称的首字/缩写词应以小写字母开始,然后以驼峰字符继续。 这有助于将它们与库types区分开来。
  3. 在VBA中,总是在每个表单/模块的开始部分放置[option explicit],这要求你将[varNametypes变暗],这将有助于debugging,并使你的代码更加明确,因此很容易理解。
  4. 在VBA中,数字使用Longtypes,早期学习与后期学习。 如果您正在实例化任何需要引用/库的对象,请始终明确声明它。 这包括Excel.Worksheet,Excel.Workbook等(例如,您可能希望您的代码在MS Access中)
  5. 在办公室你想要禁用的第一个设置之一是popup错误窗口,也使用debug.print和直接框几次。
  6. 一般情况下,正如您从C ++中所了解的那样,花点时间,尝试在第一次尝试时写出正确的代码,因为这样可以节省您的debugging时间。 尽量不要急于和保持咖啡和健康的零食。 祝好运并玩得开心点 :)