谁在Excel电子表格中欠钱算法

时间:2013-05-06 12:46:02

标签: excel spreadsheet

我有一群人在一段时间内有不同的开支。在此期间之后,每个人都有平衡。在excel中看起来像这样:

人A:6
人B:10
人C:-7,5
人D:-8,5

在此期间之后将进行和解。我目前通过手动完成此操作。这导致:

C人向人A支付6 C人向人B支付1.5 D人向人乙支付8,5。

A人从C中获得6 B人获得1.5人格 庇隆B从人D得到8,5。

(涉及更多人时,有多种解决方案。)

问题在于我必须将这个程序应用于一大群人。所以我的问题是:'如何通过使用Excel电子表格算法或宏来应用这个'谁'过程?'。

3 个答案:

答案 0 :(得分:1)

谁欠谁的配对有多重要?我问的原因是 - 很容易弄清楚每个人的总费用,然后确定谁欠钱以及谁需要退款。如果一个人可以成为“银行家”,他可以收取所有应付款项并支付所有退款。

更简单的问题,如果你有人愿意成为银行家。

尝试将所有内容配对很可能不会产生确切的答案,或者可能需要一个或多个人向多个人付款 - 以及一个或多个人试图从多个其他人那里收款。

答案 1 :(得分:1)

我也制作了一个excel版本,但它在Open office中。你能下载吗?以下宏可能会自行运行。如果它不应该是小的东西。它在OOO中工作正常,并保存为Excel 97/2000工作簿文档。

'this might not be needed in Microsoft Excel, comment it out
Option VBASupport 1 'OWES

Option Explicit
'Cells(row, col), 
Private Sub cmd1_Click()
'data is same sheet, from row 4, column 4
'row 4 has names in columns, so 4,4 has name 1, 4,5 has name 2
'row 5 has amounts spent like 6, -10
'output is in columns 3 and 5

dim i 
dim j,s as String, sum1
s=""

'get number of cells used in row 4 and check if corresponding row 6 column has a number value too
i = 4
sum1=0
do while(cells(4,i).Value <> "" and i < 500) 

    j = CDbl(cells(5,i).Value)
    sum1 = sum1 + j
    if j <> cells(5,i).Value then
        MsgBox "Col " & i & " not a number?"
        End
    end if
    i=i+1
loop
if i > 499 then
    Msgbox "too many cols"
    End
end if

If sum1 > 0.3 or sum1 < -0.3   then
    Msgbox "Sum is not near 0 :" & sum1
    End
End if


Dim colCnt as Integer
colCnt = i - 4
cells (7,1).Value = "Col count = " & colCnt
Dim spent(colCnt) as Double
Dim owes1(colCnt ) as String
Dim owes2(colCnt ) as String


for i= 4 to colCnt + 3
    spent(i - 3) = CDbl(cells(5,i).Value)
Next

Dim cnt,lastNeg, abs1,maxPay  ' safety var for never ending loops, only if data bad like many cols and more than .1 diffs
lastNeg = 4
dim lastPay1
lastPay1 = 10
dim ii,jj,c1,c2,toPay
toPay = 0
On Local Error Goto errh
for i= 4 to colCnt + 3
    cnt = 0
    ii = i - 3
    c1 =  spent(ii)
    'Cells(6,i) = "ok "
    if spent(ii) > 0.1 and cnt < colCnt Then '//has to take
        cnt = cnt + 1
        for j = lastNeg  to colCnt + 3 ' ; j < people.length && spent(ii) > 0.1; j++)
            jj = j - 3
            's = s & Me.Cells(ii,j) & " " 
            if spent(ii) > 0.1 then
                if spent(jj) < -0.1 Then ' //has to give and has balance to give
                    c1 =  spent(ii)
                    c2 =  spent(jj)
                    lastNeg = j
                    abs1 = spent(jj) * -1'//can use absolute fn
                    maxPay = abs1
                    if(maxPay > spent(ii)) Then
                        toPay =  spent(ii)'
                    else 
                        toPay = abs1
                    End if
                    spent(ii) = spent(ii) - toPay
                    spent(jj) = spent(jj) + toPay
                    Cells(lastPay1, 3).Value = Cells(4 , j) & " pays " & toPay & " to " & Cells(4 , i )
                    Cells(lastPay1, 5).Value  = Cells(4 , i) & " gets  " & toPay & " from " & Cells(4 , j)
                    lastPay1 = lastPay1 + 1
                End if

            End if
        Next
    End if
Next
Msgbox "Done"
err.Clear
if err.Number <> 0 Then
  errH:
  dim yy
  yy = msgBox("err " & err.Number & " " & err.Description & " Continue", 2)
  if yy = vbYes Then
     Resume Next
  End IF
End IF
End Sub

预订http://sel2in.com/prjs/vba/profile(欠款)

可以看到http://www.excel-vba.com/http://office.microsoft.com/en-in/training/get-in-the-loop-with-excel-macros-RZ001150634.aspx excel中的帮助也很有用(宏编辑器中的f1,可以通过按f1选择关键字或类型并获取上下文相关帮助)

答案 2 :(得分:0)

请参阅http://sel2in.com/pages/prog/html/owes.html

Javascript fn

<form>

Paste tab seperated list of people on first line, Second line has blanace - positive means they spent more than others, negative means other spent on them (they owe)
<br>
<textarea id=t1 rows=3 cols=70></textarea>

</form>

<button onclick=calcOwes() >Calc owes</button>

<br>
<b>Result:</b>
<div id=result>Will appear here if data is good</div>
<br>
<b>Parsed data for debug:</b>
<div id=data1>Will appear here if data is good</div>

<br>
<hr>
<script>
function calcOwes(){
/**
2013    Tushar Kapila
If Person A: 6
Person B: 10
Person C: -7,5
Person D: -8,5

Then Person C pays 6 to person A.
Person C pays 1,5 to person B.
Person D pays 8,5 to person B.
*/
s = document.getElementById("t1").value

    var line = s.split("\n")
    //v = confirm("Your Data looks okay?:\n" + s)
    //if(!v){ return;}
    if(s.length < 2 || s.indexOf("\n") < 0){
        alert("No line sep ")
        return
    }
    people = line[0].split("\t")
    spent = line[1].split("\t")
    spent2 = line[1].split("\t")
    if(spent.length < 2){
        alert("Bad data, no spent data " + spent.length + "; 0 " + spent[0] + "; 1 " +  + spent[1])
        return
    }
    if(people.length != spent.length){
        alert("People and amounts do not tally. make sure no tabs inside names, spaces are okay")
        return
    }

    sum  = 0;
    data1o = document.getElementById("data1")
    data1o.innerHTML = "";
    for(i = 0;i < people.length; i++){
        spent[i] = spent[i].trim()
        spent[i] = parseFloat(spent[i])
        sum += spent[i]
        s = (1 + i) + " \"" + people[i] + "\" :" + spent[i] + ";<br>"
        data1o.innerHTML += s;
    }
    if(sum > 0.2 || sum < -0.2){
        v = confirm("Sum (" + sum + ")is not zero continue?")
        if(!v){return;}
    }
    lastNeg = 0;
    payDetails = new Array();
    getDetails = new Array();
    lastPay = 0;

    for(i = 0;i < people.length; i++){
        cnt = 0;
        if(spent[i] > 0.1 && cnt < people.length){//has to take
            cnt++
            for(j = lastNeg; j < people.length && spent[i] > 0.1; j++){
                if(spent[j] < -0.1){//has to give and has balance to give
                    lastNeg = j;
                    abs1 = spent[j] * -1;//can use absolute fn
                    maxPay = abs1
                    if(maxPay > spent[i]){
                        toPay =  spent[i];
                    }else{
                        toPay = abs1
                    }
                    spent[i] -= toPay
                    spent[j] += toPay
                    payDetails[lastPay] = people[j] + " pays " + toPay + " to " + people[i]
                    getDetails[lastPay] = people[i] + " gets  " + toPay + " from " + people[j]
                    lastPay++;
                }
            }
        }
    }
    s = ""
    s2 = ""
    for(i = 0;i < lastPay; i++){
        s = s + payDetails[i] + "<br>"
        s2 = s2 + getDetails[i] + "<br>"
    }
    document.getElementById("result").innerHTML = s + "<br>" + s2
}

</script>
 <br>Sample input 1 (tabs there?)
 <br><pre>
 a  b   c   d
 6  10  -7.5    -8.5
 </pre>

 <br>Sample input 2
 <pre>
 Anna Dan   Bobby Scareface Colly   Doc Egg face
 -6 10  -7.3    -8.33   11.67
 </pre>