我一直在努力为我的低音俱乐部创建随机配对算法。我们的想法是将A列(Boaters)中的值与B列中的值(非划船者)配对。如果没有更多的非划船者,除非只有一名未配对的划船者,否则任何剩余的划船者都应配对。
我在线发现了一些VBA代码,在Excel中运行良好,但我所有的俱乐部内容都在Google表格中,我希望在GAS中具有相同的配对功能。
我已经尽力将VBA代码转换为GAS,但说实话,我对VBA有一些经验,而且我仍然是GAS的相对新手,尽管我正在学习。
我已经粘贴了下面的两个VBA功能,然后是我一直在努力的GAS转换。评论显示我遇到麻烦的地方,特别是被叫排序功能(vSortM),虽然我欢迎第二组眼睛,以确保我没有错误地编码其他东西。
任何人都可以建议我是否正确执行从VBA到GAS的转换?
我在网上找到的VBA中的配对算法:
Option Explicit
Sub test()
Dim Boters(), NonBoters(), i As Long, x As Long
Boters = Range("a1", Range("a" & Rows.Count).End(xlUp)).Value
Redim Preserve Boters(1 To UBound(Boters), 1 To 2)
NonBoters = Range("b1", Range("b" & Rows.Count).End(xlUp)).Value
Redim Preserve NonBoters(1 To UBound(NonBoters), 1 To 2)
Randomize
For i = 1 To UBound(Boters)
Boters(i, 2) = Rnd
Next
For i = 1 To UBound(NonBoters)
NonBoters(i, 2) = Rnd
Next
VSortM Boters, 1, UBound(Boters), 2
VSortM NonBoters, 1, UBound(NonBoters), 2
x = Application.Min(UBound(Boters), UBound(NonBoters))
With Cells(1, 4).Resize(x, 2)
.CurrentRegion.ClearContents
.Columns(1).Value = Boters
.Columns(2).Value = NonBoters
End With
If x < UBound(Boters) Then
For i = x + 1 To UBound(Boters) Step 2
If i + 1 > UBound(Boters) Then Exit For
Cells(i, 4).Value = Boters(i, 1)
Cells(i, 5).Value = Boters(i + 1, 1)
Next
End If
End Sub
Private Sub VSortM(ary, LB, UB, ref)
Dim M As Variant, i As Long, ii As Long, iii As Long, temp
i = UB: ii = LB
M = ary(Int((LB + UB) / 2), ref)
Do While ii <= i
Do While ary(ii, ref) < M
ii = ii + 1
Loop
Do While ary(i, ref) > M
i = i - 1
Loop
If ii <= i Then
For iii = LBound(ary, 2) To UBound(ary, 2)
temp = ary(ii, iii)
ary(ii, iii) = ary(i, iii): ary(i, iii) = temp
Next
ii = ii + 1: i = i - 1
End If
Loop
If LB < i Then VSortM ary, LB, i, ref
If ii < UB Then VSortM ary, ii, UB, ref
End Sub
我尝试在GAS中转换配对算法
function test() {
//Get values for Column A and Column B starting at Row 5
var ssMatch = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Pairings');
var bRange = ssMatch.getRange("A5:A").getValues();
var nBRange = ssMatch.getRange("B5:B").getValues();
//Determine length with data to exclude blansk
var bLast = bRange.filter(String).length;
var nBLast = nBRange.filter(String).length;
//Get values for boaters & nBoaters without blanks
var boaters = ssMatch.getRange(5,1,bLast).getValues();
var nBoaters = ssMatch.getRange(5,2,nBLast).getValues();
// Populate boaters & nBoaters arrays using random numbers
for (var i = 0; i < bLast; i++) {
boaters[i][1] = Math.random();
Logger.log(boaters);
}
for (var j = 0; j<nBLast; j++) {
nBoaters[j][1] = Math.random();
Logger.log(nBoaters);
}
vSortM (boaters, 1, bLast, 1);
vSortM (nBoaters, 1, nBLast, 1);
//Determine whether there are more boaters or non-boaters
var x = Min(bLast, nBLast);
//Write boater & nBoater values in Columns
//NEED SOME HELP HERE: Certain this isn't correct for GAS
Cells(1,4).Resize(x, 2);
Cells.CurrentRegion.ClearContents;
Cells.Columns(1).setValues(boaters);
Cells.Columns(2).setValues(nBoaters);
//If no more nBoaters, pair remaining unpaired boaters
if (x < bLast) {
for (var i = x + 1; i<bLast; i = i + 2) {
if (i + 1 > bLast) { break;}
else {
//THINK I DID THIS RIGHT, BUT NOT SURE
ssMatch.getRange(i,4).setValue(boaters[i][0]);
ssMatch.getRange(i,5).setValue(boaters[i+1][0]);
}
}
}
}
//Having some trouble converting this from VBA to GAS
// not sure how to deal with the ary parameter and m statement
function vSortM(ary, lB, uB, ref) {
var temp = 0;
var i = uB;
var ii = lB;
var m = [parseInt((lB + uB) / 2), ref];
while (ii <= i);{
while ([ii, ref] < m); {
ii++;
while ([i, ref] > m); {
i--;
}
if (ii <= i); {
for (var iii = 0; i<=(ary, 2);) {
temp = [ii, iii];
[ii, iii] = [i, iii];
[i, iii] = temp;
}
ii++;
i--;
}
}
if (lB < i) {
vSortM(ary, lB, i, ref);
}
if (ii < uB) {
vSortM(ary, ii, uB, ref);
}
}
}
答案 0 :(得分:2)
首先,我必须同意评论中的其他人。问题太宽泛了。在https://stackoverflow.com/help/dont-ask中,它表示问题应该是合理的范围。
从我在您的代码中看到的,您寻求帮助。
//NEED SOME HELP HERE: Certain this isn't correct for GAS
Cells(1,4).Resize(x, 2);
Cells.CurrentRegion.ClearContents;
Cells.Columns(1).setValues(boaters);
Cells.Columns(2).setValues(nBoaters);
通过使用GAS编写得非常好的文档很容易弄清楚(在去其他地方之前总是先参考它)。在GAS中,您实际上是在使用类(或者对象,如果您愿意)。在这里,您需要sheet class调整行和列的大小(2个单独的函数),然后调整range class(从工作表类中检索)以清除和设置值。
//THINK I DID THIS RIGHT, BUT NOT SURE
ssMatch.getRange(i,4).setValue(boaters[i][0]);
ssMatch.getRange(i,5).setValue(boaters[i+1][0]);
取决于您想要完成的任务。这里的语法是正确的,您为单个单元格设置了一个值。请注意,在Google工作表中,最好尝试批量调用此类调用。因此,不是逐个单元地设置值,而是获得从A1到B20的范围,并使用2D数组一次设置所有值。
最后,您需要澄清第二个功能必须做什么以及它做什么不正确。也许共享一个最小的示例表(阅读here关于Minimal,Complete和Verifiable示例)?