당신은 첫 번째 세 개의 고유 한 값을 얻을 말 : 주셔서 감사합니다 도움을, 여기에 코드입니다. 나는 그 문제를 복제 할 수 없다. 내 코드를 시험해보고 문제가 해결되는지 확인하십시오. 그렇지 않다면 나는 당신의 데이터의 본질을 잘못 이해했다고 가정 할 수 있습니다. 내 테스트 데이터의 이미지를 게시합니다. 내 데이터가 귀하의 데이터와 다른 점을 알려 주셔야합니다.
Rory의 의견은 적절한 고급 기술이 있음을 나타냅니다. 코드를 많이 변경했지만 이러한 고급 기술은 사용하지 않았습니다. 나는 너에게 생각할 것을 충분히 주었다. 내 모든 포인트와 모든 나의 변화에 대한 이유를 숙지하십시오. 그러면 다음 단계로 나아갈 준비가 될 것입니다.
일반 포인트
Workbooks.Open
엑셀의 현재 사본에서 새 통합 문서를 엽니 다. 당신은 필요하지 않습니다 :의 ActiveCell
에서 값을 선택하는 것이 필요하고 적절한, 또는를 기준으로 할 때
Dim ABC_App As Excel.Application
Set ABC_App = carWBook.Parent
ABC_App.Visible = True
은 시간이 있습니다. 이게 그 중 하나라고 확신합니까? 사용자가 커서를 놓은 행의 열 29 열에 원본 통합 문서의 이름을 저장해야합니까? 그들은 이전 워크 북의 이름을 잊어 버리고 떠날 것입니까? 원본 통합 문서 이름을 가져 오는 가장 신뢰할 수있는 방법인지 확인하십시오.
원본 워크 시트가 열려있는 상태에서 원본 통합 문서가 저장되었다고 가정합니다. 이게 사실일까요?
나는 With
문장을 사용했습니다. 이것은 정확한 접근 99 %의 시간이 될 것입니다. 이 경우에 올바른 접근법인지 알 수 있습니다.
워크 시트를 활성화하지 마십시오. 특히 Excel에서 새 워크 시트를 활성화 할 때마다 화면이 다시 표시되기 때문에 Application.ScreenUpdating = False
을 생략하면 느린 명령입니다.
당신은 현재 셀의 행의 열 (29)에서 값을 얻을 즉시 Worksbooks.Open
성명에서 그것을 사용할 수 있습니다. 값이 null이 아니며 액세스 할 수있는 통합 문서의 경로와 이름인지 확인하지 않습니다. 가능한 많은 오류를 확인하는 습관을 가지므로 강조 표시된 VBA 문과 VBA 인터프리터의 불분명 한 오류 메시지가 아닌 이해하기 쉬운 오류 메시지와 우아한 종료를 사용자에게 제공 할 수 있습니다. i
및 n
같은
피 이름.이 매크로를 작성하는 동안 i
과 n
이 무엇인지 기억할 것입니다. 6 개월에서 12 개월 사이에이 매크로를 업데이트해야 할 때 기억하십니까? 나는 RowSrcCrnt
과 RowDestCrnt
과 같은 이름을 사용합니다. 나는 당신에게 나의 명명 체계를 좋아하지 않고, 당신 자신의 체계를 가지라고 요청하고있다. 저는 몇 년 전에 쓴 매크로로 돌아가서 모든 변수가 무엇인지 알 수 있습니다. 이전 매크로를 업데이트해야하는 경우 시간 절약 효과가 있습니다.
내가 같은 11, 29 및 30 오늘 매직 넘버를 부르는 피, 데이터 열 (11)에 확인하지만 당신은 새로운 열이 추가되지 않는다는 것을 확신합니다. 워크 시트 재배치 후에 매크로를 업데이트하더라도 작업은 악몽이 될 수 있습니다. 상수를 사용하면 문장을 입력하는 데 조금 시간이 걸리지 만 의미있는 이름을 사용하면 무언가가 변경 될 때 많은 시간을 절약 할 수 있습니다. 종종 상수 값을 업데이트하는 것만으로도 충분합니다.
매크로가 포함 된 통합 문서 내에서 워크 시트의 내 버전은 매크로하기 전에 다음과 같습니다
이 실행 내 테스트 데이터 및 코드 :
워크 시트의 내 버전에서 데이터가 포함 된 통합 문서는 다음과 같습니다.
매크로가 포함 된 통합 문서 내에서 워크 시트의 363,210
내 버전은 매크로를 실행 한 후 다음과 같습니다
위의 이미지는 코드에 대한 이해를 일치합니다.
내 코드는 다음과 같습니다. 나는 모든 변화를 설명했다. 이러한 변경 중 일부는 현재 요구 사항에 부적절 할 수 있습니다. 내 변경 사항은 대부분 정확한 시간이 될 것이지만 현재 정확한지 알 수 있습니다. 내 코드로 일해라. 필요하다면 질문으로 다시 돌아 오지만, 당신이 스스로 변화를 이해할 수 있으면 더 빨리 개발할 수 있습니다. 행운을 빕니다.
Option Explicit
Sub PrintCarID()
' * I name my constant and variables using a sequence of keywords.
' * The first keyword identifies the type of information. For example:
' Wsht for worksheet, Wbk for workbook, Row for row, Col for column and
' Rng for range.
' * Each subsequent keyword narrows the constant or variable down until
' I hsve a name that is unique within the macro or project.
' * If I have more than one workbook, the keyword following Wbk will identify
' the workbook. I know nothing about your workbooks and worksheets so have
' named them Source and Destination and have used keywords Src and Dest.
' * This is my system which you may not like. If you do not like mine,
' invent your own. Naming your constants and variables makes large macro
' much easier to follow particularly if you return to one after 6 or 12
' months.
' * 11 and 30 in your code are what I call magic numbers. You say "Abracadabra!"
' and good (or bad) things happen but you do not know why. Replacing 11 and 30
' with names makes the code easier to understand and easier to maintain.
Const ColSrcId As Long = 11
Const ColDestId As Long = 30
' * I do not like using the cell that was active when the macro was called
' unless this is important to how the user controls the macro. Switch
' back to your approach if necessary.
Const RngWbkSrcName As String = "AC1"
' Chamge these values if you add header rows
Const RowSrcDataFirst As Long = 1
Const RowDestDataFirst As Long = 1
' * You use the active worksheet in the workbook containing the macro and the
' worksheet active when the source worksheet was saved. This may be
' necessary for your macro but I have coded on the assumption it is not.
' Switch back to ActiveWorkbook if necessary. Better replace "Destination"
' and "Source" with your names.
Const WshtDestName As String = "Destination"
Const WshtSrcName As String = "Source"
Dim CarIdLast As String
Dim Path As String
Dim RowDestCrnt As Long
Dim RowSrcCrnt As Long
Dim RowSrcLast As Long
Dim WbkDest As Workbook
Dim WbkSrc As Workbook
Dim WbkSrcName As String
Dim WshtDest As Worksheet
Dim WshtSrc As Worksheet
' * ThisWorkbook explicitly identifies the workbook containing the macro
' It is possible to execute a macro in a non-active workbook so ActiveWorkbook
' is not necessarily the workbook containing the macro
Set WbkDest = ThisWorkbook ' The workbook containing the macro
With WbkDest
Set WshtDest = Worksheets(WshtDestName)
With WshtDest
' * carPath may be a meaningful name for you but I have used my own naming
' convention. If "car" is meaningful, I would use a name like WbkCarName
' or WbkCarPath.
WbkSrcName = .Range(RngWbkSrcName).Value
End With
End With
If WbkSrcName = "" Then
Call MsgBox("The name of the source workbook is missing.", vbOKOnly)
Exit Sub
End If
' * I like to place all linked workbooks and files in the same folder
' since this makes it easier to handle them. With your approach the
' user has to include the full path within the workbook name. With
' my approach the user only has to include specify the file name.
Path = WbkDest.Path & "\"
' * Check the path and file exists. I could check the path exists first
' but I doubt that would provide much extra help to the user
If Dir$(Path & WbkSrcName) = "" Then
Call MsgBox("I cannot find """ & Path & WbkSrcName & """.", vbOKOnly)
Exit Sub
End If
' * I have checked the file exists but the open may still fail because,
' for example, I may not have read permission. There is little I can
' do to avoid such errors. Te statements around the Workbook.Open
' switch off normal error processing so I can issue my own error
' message rather than have the VBA halt on the Workbook.Open statement.
Err.Clear
On Error Resume Next
Set WbkSrc = Workbooks.Open(Path & WbkSrcName)
On Error GoTo 0
If Err.Number <> 0 Then
Call MsgBox("My attempt to open """ & Path & WbkSrcName & """failed. " & _
"The reason I have been given is: " & Err.Description, vbOKOnly)
Exit Sub
End If
' * You step the source row number then check it but output to the destination
' row then step. I like to be consistent unless there is good reason not to
' be consistent. I step afterwards for both rows.
' * You do not allow for header rows. This may be correct at the moment but
' will it always be correct. I allow for header rows to be added easily
' by making the first data row a constant
RowDestCrnt = RowDestDataFirst
CarIdLast = "" ' No last Car Id
With WbkSrc
' * If I was particularly careful, I would check a worksheet with name
' WshtSrcName exists before trying this statement.
Set WshtSrc = Worksheets(WshtSrcName)
With WshtSrc
' * This gets the last used row in column ColSrcId. This allows me to
' use a For-Loop which I find clearer.
RowSrcLast = .Cells(Rows.Count, ColSrcId).End(xlUp).Row
For RowSrcCrnt = RowSrcDataFirst To RowSrcLast
If CarIdLast <> .Cells(RowSrcCrnt, ColSrcId).Value Then
' * New value for CarId
If CarIdLast <> "" Then
' * Have a value to copy to the destination worksheet
WshtDest.Cells(RowDestCrnt, ColDestId).Value = CarIdLast
RowDestCrnt = RowDestCrnt + 1
End If
CarIdLast = .Cells(RowSrcCrnt, ColSrcId).Value
End If
Next
' * Output final value
If CarIdLast <> "" Then
' * Have a value to copy to the destination worksheet
WshtDest.Cells(RowDestCrnt, ColDestId).Value = CarIdLast
RowDestCrnt = RowDestCrnt + 1
End If
End With
' * Close the source workbook without saving any changes. There should not
' be any changes but best to be safe. Without SaveChanges the user will
' be asked if changes are to be saved.
.Close SaveChanges:=False
End With
End Sub
열 11에서 최종 값을 이동하면 첫 번째 빈 행에서 'CarID'를 설정합니다. 그런 다음 비어 있지 않은 행을 찾을 때까지 반복합니다. 문자열'i'는 정수로 취급되어 32768에서 오버플로되는 것 같습니다. 긴'i'의 경우, 존재하지 않는 행에 액세스하려고하면 오류가 발생합니다. 최대 행 수는 사용중인 Excel 버전에 따라 다릅니다. 코드를 시험해보고 실패 할 때'i'의 값을 말해주십시오. 제 이론이 맞다면 수정 된 버전의 코드로 답을 게시 할 것입니다. –
원본 데이터에 머리글 행이있는 경우 사전 또는 고급 필터 만 사용할 수 있습니다. – Rory
당신이 맞았을 때 토니의 가치는 32767 (문자열 일 경우)입니다. 나는 코드가 중재 루프에 carID = ""면 exit를 추가하도록 수정했습니다. 그러나 심지어 코드는 여전히 문서의 첫 번째 3 개의 고유 한 값만 인쇄합니다. –