AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.06.2008, 18:36   #21  
IvanOFF is offline
IvanOFF
MCTS
MCBMSS
 
61 / 75 (3) ++++
Регистрация: 22.09.2005
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
В Excel нет отдельного типа "Время" (не путать с форматом, отображающим только время, без даты). Есть единый тип "Дата", в котором собственно дата является целым числом (до запятой), а время дробным (после запятой). Особенно хорошо это видно при программировании на VBA: есть тип Date, но нет Time.

Чтобы загрузить время в Аксапту следует до импорта из Excel в самом Excel:
- либо превратить время в вещественный тип путем назначения столбцу формата General (Общий);
- либо превратить его в вещественный тип, умножить на 86400 и тащить в Аксапту в виде общего количества секунд;
- либо распарсить исходное время на часы, минуты и секунды, импортировать эти 3 значения по отдельности и уже в Аксапте собирать,
- либо превратить в текст вида "09:30:00" при помощи функции вроде =ТЕКСТ(A1,"[ЧЧ]:ММ:СС").
Спасибо! Теперь все понятно!
Старый 02.10.2008, 17:52   #22  
Stainless is offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 87 (3) ++++
Регистрация: 26.01.2007
Как перейти к конкретной записи recordset?
Почитал help на эту тему, там есть метод move, но заставить его работать у меня не получилось.

Ответ нашелся очень просто:
X++:
recordset.move( NumRecords, Start );
более подробно: http://www.devguru.com/Technologies/...dset_move.html

Последний раз редактировалось Stainless; 02.10.2008 в 18:05.
Старый 02.10.2008, 19:02   #23  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
хм, в хелпе тоже самое, вроде:
Цитата:
Сообщение от файл ADO210.CHM
Move Method

Moves the position of the current record in a Recordset object.

Syntax

recordset.Move NumRecords, Start
Или отсутствие скобок смутило? В хелпе синтаксис для Visual Basic приводится.
Старый 07.11.2008, 13:21   #24  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
? э-хе-хе...
Испытываю возобновление интереса к теме и вот в связи с чем. ADODB.Recordset имеет полезнейшие свойства Filter и Sort, которыми можно эффективно пользоваться, фильтруя исходный набор или изменяя порядок записей исходного Recordset'а и далее перебирая в цикле нужные записи в нужном порядке.

Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки. Увы, при управлении Excel из Аксапты этого не происходит:

X++:
static void Job103(Args _args)
{
    #CCADO

    ComExcelDocument_RU doc = new ComExcelDocument_RU();
    COM                 rst = new COM('ADODB.Recordset');

    COM     xlApp;
    COM     wbook;
    COM     activeSheet;
    COM     range;
    COM     flds,fld;

    int     i;
    ;

    doc.NewFile('',false);
    wbook = doc.getComDocument();

    xlApp = wbook.Parent();
    activeSheet = xlApp.ActiveSheet();

    flds = rst.Fields();

    flds.Append('myField1', #adVarChar, 50);
    flds.Append('myField2', #adInteger);
    
    rst.Open();

    for (i=1;i<=1000;i++)
    {
        rst.AddNew();
            fld = flds.Item(0); fld.Value(int2str(i));
            fld = flds.Item(1); fld.Value(i*2);
        rst.Update();
    }

    rst.Filter("myField1 Like '*24*'");
    rst.Sort('myField1 DESC');

    rst.MoveFirst();

    range = activeSheet.Range('A1');
    range.CopyFromRecordset(rst, 300);

    range = activeSheet.Range('A1000');
    range.CopyFromRecordset(rst, 300);

    doc.visible(true);

    
    // чтобы показать, что набор действительно фильтруется и сортируется
    rst.MoveFirst();
    while (! rst.EOF())
    {
        info(strFmt('%1 --- %2', 
                    new CCADOField( flds.Item(0) ).value(),
                    new CCADOField( flds.Item(1) ).value()));
        rst.MoveNext();
    }
}
Поведение метода CopyFromRecordset в этом примере не соответствует ожиданиям. Он не учитывает не только сортировку и фильтрацию, но и декларированное в справке продвижение указателя текущей записи. Так, по здравой логике, первый оператор "range.CopyFromRecordset(rst, 300);" должен вывести в Excel первые 300 записей и установить указатель на 301-ю. Второй же оператор "range.CopyFromRecordset(rst, 300);" должен вывести следующие 300 записей: с 301-й по 600-ю и остановиться на 601-й.

Но этого не происходит. Вместо этого - и начиная с ячейки A1, и начиная с ячейки A1000 - одинаково выводятся первые 300 записей исходного набора. А хотелось бы, чтобы вывелись только 20 записей с ячейки A1, т.е. те записи, которые пример выводит в окно Infolog.

Возможно мои претензии необоснованы и CopyFromRecordset должен себя вести именно так, как ведет себя в этом примере? Я уже было засомневался, вернее, почти отказался от своих "претензий", но решился на еще одну проверку - в самом Excel на VBA:
Код:
 
Sub Job103_VBA()

    Dim i As Integer
    
    Dim rst As Object
    Dim flds As Object
    
    Dim xlApp As Excel.Application

    Set rst = CreateObject("ADODB.Recordset")
    'я сознательно создал rst через CreateObject, а не как New ADODB.Recordset, 
    'чтобы не искать ссылку на ADO через Tools\References    
    
    Set flds = rst.Fields
    
    flds.Append "myField1", 200, 50 '200 = adVarChar
    flds.Append "myField2", 3 '3 = adInteger
    
    rst.Open
    
    For i = 1 To 1000
        rst.AddNew
            rst.Fields(0).Value = i
            rst.Fields(1).Value = i * 2
        rst.Update
    Next i
    
    rst.Filter = "myField1 Like '*24*'"
    rst.Sort = "myField1 DESC"
    
    rst.MoveFirst
    
    'Set xlApp = New Excel.Application
    Set xlApp = Application
    
    xlApp.Workbooks.Add
      
    xlApp.Range("A1").CopyFromRecordset rst, 300
    xlApp.Range("A1000").CopyFromRecordset rst, 300
    
    xlApp.Visible = True
    
End Sub
Что скажете о результате? Он такой, как хотелось! Ура? Увы, нет. Закомментируйте строку "Set xlApp = Application" и раскомментируйте строку выше, т.е. должно стать вот так:
Код:
 
    Set xlApp = New Excel.Application
    'Set xlApp = Application
Таким образом, теперь мы из Excel создаем другой Excel и выводим рекордсет в этот другой. Результат такой же, как при выводе из Аксапты - не такой, как хочется.

Есть ли у кого какие-нибудь соображения? Может, кто-нибудь интересующийся продвинуто заглянет какими-нибудь крутыми вьюерами в тайны происходящих процессов COM-автоматизации? Может быть удастся победить ситуацию использованием каких-нибудь COMDispFunction?


P.S. Проделал даже такой финт. Создал шаблон xlt, в который зашил VBA-процедуру:
Код:
 
Sub myCopyFromRecordset(ByVal rng As Range, ByVal rst As ADODB.Recordset, ByVal maxRows As Integer)
    rng.CopyFromRecordset rst, maxRows
End Sub
Из Аксапты создал новый файл на базе этого шаблона и вызвал процедуру строкой:
X++:
    xlApp.Run('myCopyFromRecordset', range, rst, 300);
Результат - тоже не тот
Старый 07.11.2008, 20:12   #25  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,503 / 1623 (60) ++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки.
Для тех, кто программировал в Access еще в DAO (а в общем-то DAO можно считать прародителем ADO) такое предположение отнюдь не резонно. Методы Filter и Sort действовали ПОСЛЕ выборки, а метод CopyFromRecordset копировал именно все записи выборки (он совершенно не собирался смотреть на методы Filter и Sort). Именно поэтому в Access приветствовалось программирование через SQL-запросы, а не через методы работы с таблицами.

Я удивлен другим. Я удивлен - что CopyFromRecordset все-таки может копировать с учетом фильтрации - но об этом видимо "помнит" только текущее приложение - т.е. поддержка реализована не на уровне "ядра" ADO
__________________
Возможно сделать все. Вопрос времени
Старый 23.04.2009, 11:32   #26  
sta[z] is offline
sta[z]
Участник
 
30 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Возникла проблема с экспортом через ADO в Excel полей с типом дата. Если переносить как adbSTR, то это не устраивает конечных пользователей (не работает нормльно фильтрация). Если переносить как adDBDate, то datenull() отображается в Excel как 02.01.1900. Применение формата "ДД.ММ.ГГГГ" к ячейке не помогает. Можно ли как-нибудь передать дату так, чтобы пустая дата не отображалась?
Старый 23.04.2009, 11:40   #27  
sta[z] is offline
sta[z]
Участник
 
30 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Сам нашел выход. Если значение поля в Axapte datenull(), то нужно писать в ADO field.value() не значение поля, а просто 0. А в Excel у активного листа выставить в false параметр DisplayZeros(0).
Старый 23.04.2009, 11:44   #28  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,432 / 312 (13) ++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от sta[z] Посмотреть сообщение
Сам нашел выход. Если значение поля в Axapte datenull(), то нужно писать в ADO field.value() не значение поля, а просто 0. А в Excel у активного листа выставить в false параметр DisplayZeros(0).
а если просто не заполнять поле в таких случаях?
За это сообщение автора поблагодарили: Gustav (2).
Старый 23.04.2009, 12:06   #29  
sta[z] is offline
sta[z]
Участник
 
30 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Тот же результат, что и с 0.
Старый 23.04.2009, 13:58   #30  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Цитата:
Сообщение от ice Посмотреть сообщение
а если просто не заполнять поле в таких случаях?
Да, именно так и надо делать. Лично я - сторонник этого способа
Цитата:
Сообщение от sta[z] Посмотреть сообщение
Тот же результат, что и с 0.
У меня так происходит, если тип поля рекордсета задавать константой adDate(7). А если взять adDBDate, которая 133, то на месте нулевых дат в Excel будут желаемые пустые ячейки. Во всяком случае для сочетания Ax 3.0 SP4 + Oracle 10 + Excel 2003 это так.
Старый 23.04.2009, 17:29   #31  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Пользуясь сегодняшнем случаем наконец-то подправил в своем рабочем классе (практически в персональном "пролетариате") метод, устанавливающий значение в поле рекордсета:
X++:
#CCADO
void setValue(anytype _fldName, anytype _fldValue)
{
    // _fldName - можно текстовое имя, а можно числовое, начиная с 1 (!), а не 0 как в самом ADO
    anytype fldName;
    ;
    if (typeof(_fldName)==Types::Integer)
        fldName = _fldName - 1;
    else
        fldName = _fldName;     

    fld = flds.Item(fldName); // COM flds и fld - полЯ и полЕ рекордсета, определены в Class Declaration

    if (! ((fld.Type()==#adDate || fld.Type()==#adDBDate) && !_fldValue) )
    {
        fld.Value(_fldValue); // если непустая дата или любое др.значение
    }
    // иначе если значение - пустая дата, то вообще не прописываем в поле
}
И теперь можно не обращать внимание на дату. А раньше приходилось делать проверку в самом цикле вывода:
X++:
if (ltDb.TransDate)
    out2xls.setValue(nextNum(),ltDb.TransDate);
Способ с проверкой в цикле, конечно, побыстрее будет, но вряд ли этот временнОй выигрыш так уж критичен, а по сему упрятывание обработки пустой даты в метод setValue выглядит комфортнее.
Старый 29.04.2009, 13:16   #32  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,499 / 4483 (156) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
А я во вспомогательном канале вывода в Excel зашел с другого конца: при создании структуры ADO.Recordset я указываю опциональный признак того, надо ли в соотв. колонке избавиться от "незначащих" значений, и после вывода просто делают замену средствами самого Excel таких значений на то, что возвращает COMVariant::createNoValue()
X++:
// очистка ячеек с "пустыми" значениями (ноль для чисел либо 01.01.1900 для дат), чтоб не надо было докручивать шаблон для их сокрытия
// _cell - ячейка, на которой в outputReportBody() вызывается метод CopyFromRecordset()
protected void clearEmptyCells(COM _cell)
{
    COMVariant  cvSrcValue;
    COMVariant  cvDstValue;
    str         strAddr;
    container   conFieldInfo;
    boolean     bClearEmpty;
    Counter     cnRows;
    Counter     n;
    COM         oRng;                                           // область, в которой будет производиться замена
    ;
    cnRows      = rstAxa.RecordCount();                         // количество выведенных строк данных
    cvDstValue  = COMVariant::createNoValue();                  // создаем пустое значение
    for (n = 1; n <= arrFields.lastIndex(); n++)
    {
        conFieldInfo = arrFields.value( n );
        if (conlen(conFieldInfo) >= #ConPosFieldInfoClearEmpty) // по умолчанию этого поля в контейнеере быть не должно
        {
            bClearEmpty = conpeek( conFieldInfo, #ConPosFieldInfoClearEmpty );
            if (!bClearEmpty)
                continue;
            cvSrcValue  = this.getEmptyVariantValue( conpeek( conFieldInfo, #ConPosFieldInfoType ) );
            if (!cvSrcValue)                                    // если вернулся null, значит, тип не поддерживается
                continue;
            // формируем адрес диапазона ячеек *относительно* _cell
            strAddr = ComExceldocument_RU::numToNameCell( n, 1 );
            if (cnRows > 1)
                strAddr += @':' + ComExceldocument_RU::numToNameCell( n, cnRows );
            oRng = _cell.range( strAddr );                      // получаем столбец внутри диапазона _cell
            oRng.Replace( cvSrcValue, cvDstValue, #xlWhole, #xlByColumns );
        }
    }
}
// возвращает COMVariant, представляющий "пустое" значение для указанного типа ADO, либо null, если указанный тип не поддерживается
protected COMVariant getEmptyVariantValue( Integer _adoType )
{
    COMVariant  ret;
    ;
    switch( _adoType )
    {
        case #adDate :
        case #adDBDate :
        case #adDBTimeStamp :
            ret = COMVariant::createFromDateAndTime( datenull(), 0 );
            break;
        case #adSingle :
        case #adDouble :
        case #adCurrency :
        case #adDecimal :
        case #adNumeric :
            ret = COMVariant::createFromReal( 0.0 );
            break;
        case #adTinyInt :
        case #adSmallInt :
        case #adInteger :
        case #adBigInt :
        case #adUnsignedTinyInt :
        case #adUnsignedSmallInt :
        case #adUnsignedInt :
        case #adUnsignedBigInt :
            ret = COMVariant::createFromInt( 0 );
            break;
        default :
            ret = null;
            break;
    }
    return ret;
}
Хотя, конечно, просто не устанавливать значение ячейки в Recordset, пожалуй, как-то "прямее"
PS. По ходу реализации наткнулся на одни "грабли": оказалось, что COMVariant::createFromDate( datenull() ) возвращает COMVariant не со значением 01.01.1900 00:00, как можно было бы ожидать, а со значением 01.01.1900 <текущее_время>!
Старый 29.04.2009, 15:17   #33  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Цитата:
Сообщение от gl00mie Посмотреть сообщение
PS. По ходу реализации наткнулся на одни "грабли": оказалось, что COMVariant::createFromDate( datenull() ) возвращает COMVariant не со значением 01.01.1900 00:00, как можно было бы ожидать, а со значением 01.01.1900 <текущее_время>!
Аналогичные грабли наблюдаются при выводе, если тип поля даты рекордсета задать #adDate (7). Причем, текущее время добавляется хвостом к нормальным ненулевым датам! А вот dateNull() выводится без "хвоста" в виде 0 (!) января 1900 года (00.01.1900).

Вот почему мы любим тип #adDBDate (133), который, как положено, сохраняет только дату без времени
За это сообщение автора поблагодарили: alex55 (1).
Старый 06.05.2010, 10:00   #34  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Как передать в Excel (через ADO) число типа real так, чтобы оно не преобразовывалось в дату? Я указывают тип поля adDouble, а Excel всё равно преобразует в дату.
Старый 06.05.2010, 10:29   #35  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,101 / 1523 (57) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Roman N. Krivov Посмотреть сообщение
Я указывают тип поля adDouble, а Excel всё равно преобразует в дату.
Не воспроизвелось
X++:
static void Job20100506(Args _args)
{
    #define.adDouble(5)
    COM Recordset;
    COM Fields;
    COM Field;
    COM Application;
    COM Workbooks;
    COM Workbook;
    COM Worksheets;
    COM Worksheet;
    COM Range;
    ;
    
    Recordset = new COM('ADODB.Recordset');
    Fields = Recordset.Fields();
    Fields.Append('Field1', #adDouble);
    
    Recordset.Open();
    Recordset.AddNew();
    Field = Fields.Item('Field1');
    Field.Value(123.45);
    Recordset.Update();
 
    Application = new COM('Excel.Application');
    Workbooks = Application.Workbooks();
    Workbook = Workbooks.add();
    Worksheets = Workbook.Worksheets();
    Worksheet  = Worksheets.Item(1);
    Range  = Worksheet.Range('A1');
    
    Range.CopyFromRecordset(Recordset);

    Recordset.Close();
    Application.Visible(true);
}
Старый 06.05.2010, 10:35   #36  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Тоже не воспроизвелось
X++:
static void Job298(Args _args)
{
    #CCADO

    COM rng  = SysExcelApplication::construct().workbooks().add().worksheets().itemFromNum(1).range('A1').comObject();
    COM rst  = new COM('ADODB.Recordset');
    COM flds = rst.Fields();
    COM fld;
    int i;

    flds.Append('MyReal', #adDouble);
    rst.Open();

    fld = flds.Item('MyReal');

    for (i=1; i<=10; i++)
    {
        rst.AddNew();
            fld.Value(100 + i/10);
        rst.Update();
    }
    rng.CopyFromRecordset(rst);
    COM::createFromObject(rng.Application()).Visible(true); // отобразим Excel
}
На чистом листе Excel не воспроизводится. Где-то у вас форматирование всё же выполняется, наверное...
Старый 06.05.2010, 10:51   #37  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Цитата:
Сообщение от Gustav Посмотреть сообщение
На чистом листе Excel не воспроизводится. Где-то у вас форматирование всё же выполняется, наверное...
Точно не воспроизводится.
А меня в шаблоне в ячейке указан формат "Число". И если передавать как строку - всё работает. Но уже второй день бьюсь над этим. Пришлось передавать поля типа "Строка"
Старый 06.05.2010, 11:11   #38  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Я обычно adDouble не использую, а использую для adCurrency.
Конечно, на файл шаблона бы взглянуть... Хотя бы на тот его фрагмент, куда пишется adDouble.
Можно выложить?
Старый 06.05.2010, 13:01   #39  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Цитата:
Сообщение от Gustav Посмотреть сообщение
Я обычно adDouble не использую, а использую для adCurrency.
Конечно, на файл шаблона бы взглянуть... Хотя бы на тот его фрагмент, куда пишется adDouble.
Можно выложить?
Выложил результат работы и шаблон
Изображения
 
Вложения
Тип файла: zip Act.zip (5.2 Кб, 32 просмотров)

Последний раз редактировалось Roman N. Krivov; 06.05.2010 в 13:05.
Старый 06.05.2010, 14:07   #40  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1145 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Роман, у меня два вопроса:
  1. Рекордсет создаете с учетом всех колонок, попадающих в область бланка? Т.е. у вас должно быть много фиктивных и немного содержательных - т.е. получается 16 содержательных где-то из 85 всего.
  2. Как вставляете новые строки? Сразу всё необходимое кол-во перед исходной 19-й строкой? Потом дополнительно еще формат этой исходной распространяете на добавленные?
Теги
ado, comvariant, excel, faq, odbc, sql, интеграция, прямой доступ, формат дат, экспорт, экспорт в excel

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Вспомогательный класс для импорта из Excel через ADO gl00mie DAX: База знаний и проекты 80 10.04.2017 10:55
gl00mie: Read Excel table via ADO Blog bot DAX Blogs 2 09.04.2010 08:32
C# and AX Development: Using ADO for interfacing AX with an external database Blog bot DAX Blogs 0 05.08.2008 05:18
casperkamal: Using ADO to read from Excel in Microsoft Dynamics Ax Blog bot DAX Blogs 2 14.05.2007 11:59
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:42.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.