Страницы: 1
RSS
Вывод данных из Аксес в таблицу Эксель, Позиционирование
 
Доброго времени суток уважаемые жители форума!
Прошу вашей помощи в решении задачи по выводу данных из Аксес в Эксель.
Есть таблица в которую ежедневно вносятся данные.  Чтоб не делать огромный файл с множеством однообразных листов, решил создать хранилище (в Аксесе), а уж из него потом подтягивать необходимое. Перенос из таблицы в Аксес выполняю по свойству Листа (Worksheet_Change). Проблема вся в том, что вероятность заполнения всех ячеек таблицы, практически равна 0. Т.е. могут быть и полностью пустые строки, и полностью пустые столбцы. Подскажите пожалуйста, как построить запрос, чтоб данные при выводе заняли каждое свою ячейку? Заранее спасибо всем!
 
Можно так, но для этого надо изменить тип поля Work на числовой.
Код
Private Sub Works()
    Dim FConn As New ADODB.Connection, pFilter As New ADODB.Recordset, sSQL As String
    sSQL = "SELECT Город1 "
    For n = 2 To 21
        sSQL = sSQL & ",Город" & n
    Next
    sSQL = sSQL & " FROM Rap ORDER BY Rap.Work;"
    sPath = ThisWorkbook.Path & "\RAP.mdb"
    FConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPath & ";"
    Set pFilter = FConn.Execute(sSQL)
    If Not pFilter.EOF Then
        Range("C8").CopyFromRecordset pFilter
    End If
    Set pFilter = Nothing
    FConn.Close:
    Set FConn = Nothing
End Sub

А это сразило меня наповал
Цитата
If Not Len(Range("K3")) = 10 Then Exit Sub    'Проверяем наличие даты в ячейке К3
Значение в ячейке ВасяПупкин пройдет
 
Здравствуйте Doober! Спасибо, что обратили внимание на тему. Увы, но Ваш вариант не подходит. т.к. Просто вытягивает данные и вставляет их на лист не учитывая их необходимое место расположение. А нужно именно расположить их в правильные строки на листе.
При открытии файла, Вы можете увидеть правильное расположение данных, которые уже внесены в таблицу Аксес, за 01.08.2016. Если в К3 поставить 01.08.2016, Ваш макрос заполнит их иначе. Но спасибо Вам!
Цитата
А это сразило меня наповал
Дата будет добавляться через форму. Просто не хотел нагромождать файл лишним.
 
Цитата
Ronin751 написал: Перенос из таблицы в Аксес
я, конечно, запуталась в названии ветки и этой фразе (туда или сюда)
Цитата
Ronin751 написал: Подскажите пожалуйста, как построить запрос, чтоб данные при выводе заняли каждое свою ячейку?
по коду - вообще не поняла, зачем на каждый (Worksheet_Change) дёргать базу...
НО попыталась позиционировать  :) - как-то так
Код
Sub test()
Dim sCon As String, sSql As String
Dim cn  As Object, p, sPath, rs As Object, m
p = ThisWorkbook.Path
sPath = p & "\RAP.mdb"
sCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPath
'Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
sSql = "SELECT * From Rap Where [Data]=" & "#" & Format(Sheets("РАПОРТ").Range("K3").Value, "mm\/dd\/yyyy") & "#" & ""
        
rs.Open sSql, sCon, adOpenStatic
With Sheets("РАПОРТ")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With

'On Error Resume Next
'a = rs.GetRows
Do While Not rs.EOF
For Each fld In rs.Fields   '.Count
If fld.Name <> "ID" And fld.Name <> "Work" And fld.Name <> "Data" Then
For Each cl In Sheets("РАПОРТ").Range("C7:X7")
    If cl.Value = fld.Name Then
        For r = 8 To LastRow
        m = Replace(Sheets("РАПОРТ").Cells(r, 2).Value, "Работа", "")
        If m = rs.Fields(1).Value Then
            If fld.Value <> 0 Then
            Sheets("РАПОРТ").Cells(r, cl.Column).Value = fld.Value
            End If
        End If
        Next
    End If
Next
End If
Next
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
End Sub
честно говоря, понимаю, что сколько вопросов у меня возникло по тех заданию - столько проверок я и внесла в код, чтобы подогнать Все  :oops:  нужные данные в нужные ячейки... мне кажется, всё вроде становится куда надо... знаю, что упростить можно (например, сразу отсечь нулевые значения - но тоже надо мудрить, и уже в самом запросе - посчитала проще взять всё, а на этапе выгрузки не вставлять нули)... проверку WHERE Work тоже, полагаю, как-то, как вы хотите, можно прикрутить... НО я совсем не поняла смысла вытягивать по каждому (Worksheet_Change) , поэтому и что тянуть не уловила - поэтому вытянула Всё... (надеюсь, правильно на 01.08.2016)... может, у вас найдутся ваши идеи по упрощению и адаптации под своё видение, согласно этому примеру кода... но мне кажется, если у вас города по разным полям, а работы по разным строкам, то всё-равно где-то бегать(прыгать) придётся - или на этапе формирования запроса, или на этапе выгрузки... как бегать и прыгать удобнее в вашем случае - пока не прониклась этим  
;)  Кстати, всем желаю побед в Rio...
P.S. и честно говоря, уже понимаю, что не совсем полный мой этот код - поскольку надо ещё и затирать прежние значения (от др. даты при смене даты) - но это уже детали... думать и дорабатывать их не буду...  поскольку, как уже и сказало, оптимальность начального тех.задания смущает
Изменено: JeyCi - 20.08.2016 21:53:57 (изменения в 25-й строке)
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
зачем это все?
по нормальному делается вот так (см. файл)
 
Цитата
Doober написал:
Можно так, но для этого надо изменить тип поля Work на числовой.
Если это сделаете, то строки стану по своим местам.
 
Здравствуйте JeyCi! Спасибо Вам большое за Вашу помощь и внимание к теме. Честно говоря Ваш макрос почему-то не выводит ни каких данных. Видно, что он работает перебирая данные за 01.08.2016, но в таблицу не выводит ничего. Спасибо Вам большое еще раз, обязательно внимательно изучу скрипт и думаю все получится. Успехов!

Уважаемый Dima S! Благодарен Вам за Ваш вариант со сводной таблицей. Мне он не подходит, поскольку необходима именно такая форма таблицы (хотя возможно причина тому, моя не осведомленность о сводных таблицах). Спасибо Вам за Ваше время!
 
Цитата
Ronin751 написал: но в таблицу не выводит ничего.
в строке 25 посчитала неправильно, надо так If m = rs.Fields(1).Value Then
- т.е. 1-й field, не 2-й, как было
- что-то выводит
(но очистить изначально по всему диапазону, чтобы не затирать каждую ячейку отдельно, для которых нет инфо в базе на дату)
p.s. полагаю как-то так... напомню - это было для Всего... (если остальные условия правильно расставила)
Изменено: JeyCi - 20.08.2016 21:37:30
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Цитата
надо так If m = rs.Fields(1).Value Then
Заработало. Спасибо!
Цитата
(но очистить изначально по всему диапазону, чтобы не затирать каждую ячейку отдельно, для которых нет инфо в базе на дату)
Так и планировалось делать. Именно по этой причине (и для общего удобства) дата будет вводится в таблицу через форму.
Спасибо Вам огромное за помощь! Удачи!
 
Doober! Простите поздно прочел Ваше сообщение.
Цитата
Если это сделаете, то строки стану по своим местам.
Даже в этом случае, столбцы соблюдаются, а строки просто ложатся с первой. Но все же спасибо Вам за то, что уделили время!
 
Ronin751. я шла по рекордсету и выкладывала по ячейкам...
полагаю, можно идти по рекордсету и формировать массив, потом его выложить (отталкиваясь от кода-примера)...
а можно и сразу взять имена полей и записи рекордсета в массивы... и уже работать с массивами для позиционирования (хоть с ними, хоть со словарём)... может и побыстрее получиться... но делать и тестить уже не буду - думаю, у вас с этим проблем не должно быть...
в массивы имена полей и рекордсет удобно брать так:
(просто размерности массива 1 и 2, в рекордсете соответствуют 2 и 1 - поэтому транспонировать)
Код
'массив верхняя шапка
ReDim a(1 To 1, 1 To rs.Fields.Count)
For k = 1 To rs.Fields.Count
    a(1, k) = rs.Fields(k - 1).Name
Next
Sheets("Лист1").[a1].Resize(UBound(a, 1), UBound(a, 2)).Value = a

'массив строк рекордсета
b = Application.Transpose(rs.GetRows)
Sheets("Лист1").[a2].Resize(UBound(b, 1), UBound(b, 2)).Value = b
ну и rs.RecordCount никто не отменял - для уточнения количества записей рекордсета (если захочется проверить их количество)
p.s.
в окне Locals обратите внимание, что Fields там с 0... RecordCount - не помню (не имела дел с этим пока)... поэтому просто правильно всё выравнивайте по колонкам и строкам... и будет ок... если захотите массивом сделать... просто очень ювелирную работу надо проделать... я пас
(мне быстрее было пробежаться Until EOF - MoveNext - оно как-то и логичнее при работе с ADO)
p.p.s
пример #2 - загнать рекордсет в массив
Изменено: JeyCi - 17.09.2016 19:58:20
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
JeyCi, спасибо Вам, что не бросаете в беде!
Поигрался немного с циклами и получил следующее (см. файл)
P.S. Пост #11 обязательно постараюсь опробовать.
Еще раз спасибо всем!
 
не знаю, заглянет ли сюда ещё хоть кто или направит хоть кого по линку  8)  какому...
опубликую ещё один ВАРИАНТ ВЫГРУЗКИ, который мне очень понравился в данном контексте - по мотивам от SAS888 - с ветки отсюда #5
нюансы на скорую руку (если захочется позиционировать по строкам на скорую руку):
1) столбцы по рекордсету должны быть в ТОЙ ЖЕ последовательности, что и на листе-выгрузки
1) ключевое поле Work выбрасывается в самый правый столбец (потом можно удалить) - оно НУЖНО, чтобы позиционировать по строкам "Работа"
2) выбрасывает ВСЁ, что вытянул... и 0-ые тоже (что в принципе по данной задаче не нужно, но вдруг когда-нибудь будет нужно)
... уж очень нравится строка кода №18  :idea:  :excl: (для позиционирования по строкам)
Код
Sub test1_VERY_CONVINIENT_BECAUSE_SHORT()
Dim sCon As String, sSql As String
Dim cn  As Object, p, sPath, rs As Object, m
ThisWorkbook.Sheets("РАПОРТ").Range("C8:W45").Cells.ClearContents
p = ThisWorkbook.Path
sPath = p & "\RAP.mdb"
sCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPathSet 
rs = CreateObject("ADODB.Recordset")
sSql = "SELECT [Город1], [Город2], [Город3], [Город4], [Город5], [Город6], [Город7], [Город8], [Город9], [Город10], [Город11], [Город12], [Город13], [Город14], [Город15], [Город16], [Город17], [Город18], [Город19], [Город20], [Город21],[Work] From Rap Where [Data]=" & "#" & Format(Sheets("РАПОРТ").Range("K3").Value, "mm\/dd\/yyyy") & "#" & ""
    
rs.Open sSql, sCon, adOpenStatic

'ВЫГРУЗКА
Arr = Application.Transpose(rs.GetRows)
For r = 8 To 45
For i = 1 To UBound(Arr, 1) Step 1
If Replace(Sheets("РАПОРТ").Cells(r, 2).Value, "Работа", "") = Arr(i, 22) Then
    c = 3
    Sheets("РАПОРТ").Cells(r, c).Resize(1, UBound(Arr, 2)).Value = Application.Index(Arr, i, 0)
End If
Next i
Next r

rs.Close
Set rs = Nothing
End Sub
Изменено: JeyCi - 27.09.2016 07:26:49
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
по задаче, конечно, есть свои нюансы... и чтобы учесть эти нюансы получится только если через  Application.Index(Arr, i, j)... подрядить Resize - (как в 1-м случае) - но при этом удаляя 0-и из итоговой массивной строчки - не видится возможным по первому (предыдущему) варианту кода... поэтому как-то так можно использовать +++ объектной модели самого XL'я... хотя по скорости на больших выборках - выигрыша, явно, иметь не будем
Код
Sub test2_Not_Quick()
Dim sCon As String, sSql As String
Dim cn  As Object, p, sPath, rs As Object, m
p = ThisWorkbook.Path
sPath = p & "\RAP.mdb"
sCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPathSet 
rs = CreateObject("ADODB.Recordset")
sSql = "SELECT * From Rap Where [Data]=" & "#" & Format(Sheets("РАПОРТ").Range("K3").Value, "mm\/dd\/yyyy") & "#" & ""
         
rs.Open sSql, sCon, adOpenStatic

'ВЫГРУЗКА
Arr = Application.Transpose(rs.GetRows)
For r = 8 To 45
For i = 1 To UBound(Arr, 1) Step 1
If Replace(Sheets("РАПОРТ").Cells(r, 2).Value, "Работа", "") = Arr(i, 2) Then
    c = 2
    For j = 4 To UBound(Arr, 2) Step 1
        c = c + 1
        el = Application.Index(Arr, i, j)
        Sheets("РАПОРТ").Cells(r, c).Value = IIf(el <> 0, el, "")
    Next j
End If
Next i
Next r

rs.Close
Set rs = Nothing
End Sub

Изменено: JeyCi - 26.09.2016 20:02:52
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Страницы: 1
Наверх