在VBA

时间:2016-12-23 19:02:33

标签: excel vba excel-vba

我正在尝试在VBA中创建一个预测算法,该算法将从数据源中搜索特定行中的字符串,并根据行号返回一个值。这是工作流程的第一步,最简单的形式有两个表格如下所示:

来源表:

This is the source table, on which the strings will be searched.

输出表:

enter image description here

这就是我想要做的事情:

  1. 拿起输出表(蓝色,黑色)的第1行中的字符串,并在源表的第1,2,3,4行中搜索它们。

  2. 如果两个字符串在一行中匹配,则输入'来自该特定行的单元格被复制到“输出”输出表中的第1行。列。

  3. 示例(第二次迭代): 从输出表行2中,拾取字符串象牙色,绿色,灰色并在源表的所有行中查询。如果源表中的一行中有3个字符串中的任何2个匹配,则复制该行的输入单元格。

    在这种情况下,Ivory和Green匹配在第1行,也在第4行。输入单元格都可以使用,但是为了有规则,让我们进行最后一次匹配(第4行)。所以' 1,8'将被复制到输出表上的第2行。

    这是我目前正在使用的流程,但我输出的输出不正确:

    For i = 2 To 5
    For j = 1 To 4
    For k = 2 To 5
    For l = 1 To 5
    
    If Cells(i, j).Value = Worksheets("SourceTable").Cells(k, l).Value And Cells(i,j).Value <> "" Then
    For a = 1 To 5
    For b = 1 To 4
    
    If Cells(i, b).Value = Worksheets("SourceTable").Cells(k, a).Value And Cells(i, b).Value <> "" Then
    Cells(i, 15).Value = Worksheets("SourceTable").Cells(k, 5).Value
    GoTo iLoop
    End If
    
    Next b
    Next a
    End If
    
    Next l
    Next k
    Next j
    iLoop:
    Next i
    

    两个表都有大约五十万行,我试图找出如何减少循环次数并使其同时工作。任何建议都会受到赞赏,这将帮助我节省大量的工时并自动化一小部分流程。谢谢!

5 个答案:

答案 0 :(得分:1)

Sub macro()
lastRowOut = Sheets("OutputTable").Range("A" & Rows.Count).End(xlUp).Row
lastRowSou = Sheets("SourceTable").Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To lastRowOut
    For j = 2 To lastRowSou
        If checkRow(j, i) >= 2 Then
            Sheets("OutputTable").Cells(i, 5) = Sheets("SourceTable").Cells(j, 6)
            Exit For
        End If
    Next j
Next i
End Sub
Function checkRow(sRow, i)
lastCol = Split(Sheets("OutputTable").Cells(i, Columns.Count).End(xlToLeft).Address, "$")(1)
counter = 0
For Each cell In Sheets("OutputTable").Range("A" & i & ":" & lastCol & i)
    If Not Sheets("SourceTable").Range("A" & sRow & ":" & "E" & sRow).Find(cell.Value) Is Nothing Then
        counter = counter + 1
    End If
Next cell
checkRow = counter
End Function

很多事情都不清楚,所以这是我做出的假设:

  • 必须匹配OutputTable中一行中的两个或多个单元格以进行预测。
  • 输出和源表的第一行包含&#34; Col1,Col2和#34;等
  • 您似乎不介意我们是使用第一个或最后一个匹配的行(来自源表),所以我选择了第一个。
    这是3循环而不是6 ..

答案 1 :(得分:1)

你可以试试这个

strings.xml

答案 2 :(得分:0)

&#39;试试这个:

&#39;首先声明一些变量:

&#39;输出表的行数     将OrNum调暗为整数  &#39; Output表的列数     Dim OcNum为整数  &#39; Source表的行数     Dim SrNum为整数  &#39; Source表的列数     将ScNum调暗为整数 &#39;循环的一些虚拟变量     将r0作为整数,将cO作为整数     将rS调整为整数,将cS调整为整数

&#39;然后假设输出表在输出表的最顶部和最左边有它的第一个单元格,它被作为单元格Z1 in以下代码

&#39;从Output表的第一个单元格开始,以某种方式获取每个值,通过修复行索引(rO),首先在(&r |)列上移动(内部循环) )输出表然后(外部循环)下降到每一行,如下所示:

import {Component} from 'angular/core';
import { Hero } from './hero';
//import { HeroDetailComponent } from './hero-detail.component';



const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' }, 
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];


@Component({
    selector: 'my-app',
//this is two way
template:`
  <h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor= "let hero of heroes"   [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

</ul>
 <my-hero-detail [hero]="selectedHero"></my-hero-detail>

`,
  styles: [`
    ignore this
  `]

}) 

export class AppComponent {
title = 'Tour of Heroes';
heroes=HEROES;
selectedHero: Hero;

onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

}

&#39;现在你不只有字符串,所以你需要检查,如果单元格中的值是字符串或数字。有VBA&#39;功能,可以提供帮助。它被称为IsNumeric。如果值是数值,它将给出“真”。如果我们有一个字符串,那么它将给出False。

For rO = 0 to OrNum - 1
    For cO = 0 to OcNum - 1
       Range("Z1").Offset(rO, cO)
    Next 
Next 

答案 3 :(得分:0)

'试试这个:

'首先声明一些变量:

'输出表的行数

 Dim OrNum as integer 

'输出表的列数

 Dim OcNum as integer

'源表的行数

 Dim SrNum as integer

'源表的列数

 Dim ScNum as integer

'循环的一些虚拟变量

 Dim rO as integer, cO as integer 

 Dim rS as integer, cS as integer 

'然后假设输出表在输出表的最顶部和最左边有它的第一个单元格,它被作为以下代码中的单元格Z1

'从Output表的第一个单元格开始,以某种方式获取每个'值,通过修复Output表的行Index(rO)然后(外部)首先在'列上移动(内部循环)循环)像这样下到每一行:

For rO = 0 to OrNum - 1
    For cO = 0 to OcNum - 1
       Range("Z1").Offset(rO, cO)
    Next 
Next 

'现在你没有字符串所以你需要检查',如果单元格中的值是字符串或数字。有VBA的功能,可以提供帮助。它叫做IsNumeric。如果值是数值,它将给出'True。如果我们有一个字符串,那么它将给出False。

For rO = 0 to OrNum - 1
     For cO = 0 to OcNum - 1
     If IsNumeric(Range("Z1").Offset(rO, cO).Value)=False then
'do something 
      End if
      Next 
Next 

对不起,伙计,我正用手机写信,我坐在洗手间。我也只有4%。我会尽快继续回答。

答案 4 :(得分:0)

'试试这个:

'首先声明一些变量:

'输出表的行数

 Dim OrNum as integer 

'输出表的列数

 Dim OcNum as integer

'源表的行数

 Dim SrNum as integer

'源表的列数

 Dim ScNum as integer

'循环的一些虚拟变量

 Dim rO as integer, cO as integer 

 Dim rS as integer, cS as integer 

然后声明一个布尔变量(仅供以后使用)

Dim bool as boolean 

'然后假设输出表在输出表的最顶部和最左边有它的第一个单元格,它被作为以下代码中的单元格Z1

'从Output表的第一个单元格开始,以某种方式获取每个'值,通过修复Output表的行Index(rO)然后(外部)首先在'列上移动(内部循环)循环)像这样下到每一行:

For rO = 0 to OrNum - 1
    For cO = 0 to OcNum - 1
       Range("Z1").Offset(rO, cO)
    Next 
Next 

'现在你没有字符串所以你需要检查',如果单元格中的值是字符串或数字。有VBA的功能,可以提供帮助。它叫做IsNumeric。如果值是数值,它将给出'True。如果我们有一个字符串,那么它将给出False。使用Function IsEmpty(),您还可以检查单元格是否为空。如果单元格为空,则函数IsEmpty将返回True。

For rO = 0 to OrNum - 1
     For cO = 0 to OcNum - 1
     bool = IsNumeric(Range("Z1").Offset(rO, cO).Value)
     bool = bool Or IsEmpty (Range("Z1").Offset(rO, cO).Value)
         If bool=False then 
 'we have a string!
 'do something 
          End if
      Next 
Next