Пример #1
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Generates the XLS from group. </summary>
        ///
        /// <remarks>   SV Milovanov, 30.01.2018. </remarks>
        ///
        /// <param name="signature">    The signature. </param>
        ///
        /// <returns>   The XLS from group. </returns>
        ///-------------------------------------------------------------------------------------------------

        public override string GenerateXlsFromGroup(GroupSignature signature)
        {
            _DCT.Execute(data =>
            {
                var groupContainer = GroupContainerList.Get(Uid);
                var group          = groupContainer.Get(signature.GetHash());

                var fields = group.Fields;
                var names  = fields.Select(q => q.Key).ToArray();

                var xls = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), $"bulletins[{group.ToString()}].xlsx"));
                if (xls.Exists)
                {
                    xls.Delete();
                }
                using (var package = new ExcelPackage(xls))
                {
                    var worksheet = package.Workbook.Worksheets.Add("Мои объявления");
                    for (var i = 0; i < names.Length; i++)
                    {
                        var cell             = worksheet.Cells[1, i + 1];
                        cell.Style.Font.Size = 14;
                        cell.Value           = names[i];
                        cell.AutoFitColumns();
                    }

                    package.Save();
                }
            });
            return(null);
        }
Пример #2
0
 ///-------------------------------------------------------------------------------------------------
 /// <summary>   Loads fields from group. </summary>
 ///
 /// <remarks>   SV Milovanov, 30.01.2018. </remarks>
 ///
 /// <param name="signature">    The signature. </param>
 ///-------------------------------------------------------------------------------------------------
 public override void LoadFieldsFromGroup(GroupSignature signature)
 {
     DCT.Execute(data =>
     {
         var groupContainer = GroupContainerList.Get(Uid);
         var group          = groupContainer.GetGroupPackage(signature.GetHash());
         Fields             = group.Fields;
     });
 }
Пример #3
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Генерирует пустую xls для группы. </summary>
        ///
        /// <remarks>   SV Milovanov, 06.02.2018. </remarks>
        ///-------------------------------------------------------------------------------------------------

        public override void GetXlsGroup(GroupSignature signature)
        {
            DCT.Execute(d =>
            {
                var groupContainer = GroupContainerList.Get(Uid);
                var groupPackage   = groupContainer.GetGroupPackage(signature.GetHash());

                var xls = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), $"new_bulletins[{groupPackage}].xlsx"));
                if (xls.Exists)
                {
                    xls.Delete();
                }

                using (var package = new ExcelPackage(xls))
                {
                    var worksheet = package.Workbook.Worksheets.Add("Мои объявления");
                    var pairs     = groupPackage.Fields;


                    var count = 0;
                    foreach (var pair in pairs)
                    {
                        var cell = worksheet.Cells[1, count + 2];

                        cell.Style.Font.Size = 14;
                        cell.Value           = pair.Key;
                        cell.AutoFitColumns();

                        var options = pair.Value.Options;
                        if (options != null && options.Length > 0)
                        {
                            var optCells = worksheet.Cells[2, count + 2, 100, count + 2];
                            worksheet.DataValidations.Clear();
                            var validation = worksheet.DataValidations.AddListValidation(optCells.Address);
                            validation.ShowErrorMessage = true;
                            validation.ErrorStyle       = ExcelDataValidationWarningStyle.warning;
                            validation.ErrorTitle       = "An invalid value was entered";
                            validation.Error            = "Select a value from the list";
                            for (var i = 0; i < options.Length; i++)
                            {
                                validation.Formula.Values.Add(options[i].Text);
                            }
                        }
                        count++;
                    }
                    package.Save();
                }
            });
        }
Пример #4
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Загружает все группы и поля Board. </summary>
        ///
        /// <remarks>   SV Milovanov, 02.02.2018. </remarks>
        ///-------------------------------------------------------------------------------------------------

        public override void ReloadGroups()
        {
            DCT.Execute(data =>
            {
                //Exit();
                //Auth();

                Thread.Sleep(1000);

                WebWorker.DownloadPage("https://www.avito.ru/additem", (doc) =>
                {
                    var groupContainer = GroupContainerList.Get(Uid);
                    groupContainer.Reinitialize();
                });
            });
        }
Пример #5
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Загружает все группы и поля Board. </summary>
        ///
        /// <remarks>   SV Milovanov, 30.01.2018. </remarks>
        ///
        /// <returns>
        /// An enumerator that allows foreach to be used to process load groups in this collection.
        /// </returns>
        ///-------------------------------------------------------------------------------------------------

        public override IEnumerable <Data.Group> LoadGroups()
        {
            var result = new List <Data.Group>();

            _DCT.Execute(data =>
            {
                Exit();
                Auth();

                WebWorker.DownloadPage("https://www.avito.ru/additem", (doc) =>
                {
                    var groupContainer = GroupContainerList.Get(Uid);
                    result             = groupContainer.Initialize().ToList();
                });
            });
            return(result);
        }
Пример #6
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Отредактировать буллетин </summary>
        ///
        /// <remarks>   SV Milovanov, 05.02.2018. </remarks>
        ///
        /// <param name="bulletinId">   Идентификатор буллетина </param>
        /// <param name="fields">       Словарь полей </param>
        ///-------------------------------------------------------------------------------------------------

        public void EditBulletin(Guid bulletinId, Dictionary <string, string> fields)
        {
            DCT.Execute(data =>
            {
                var dbBulletinInstance = data.Db1.BulletinInstances.FirstOrDefault(q => q.Id == bulletinId);
                if (dbBulletinInstance != null)
                {
                    var dbGroup        = data.Db1.Groups.FirstOrDefault(q => q.Id == dbBulletinInstance.GroupId);
                    var groupContainer = GroupContainerList.Get(Uid);
                    var groupPackage   = groupContainer.GetGroupPackage(dbGroup.Hash);

                    WebWorker.Execute(() =>
                    {
                        DCT.Execute(d =>
                        {
                            WebWorker.NavigatePage(Path.Combine(dbBulletinInstance.Url, "edit"));
                            Thread.Sleep(1000);

                            var fieldSetter = FieldContainerList.Get(Uid);
                            fieldSetter.LoadFieldsFromGroup(new GroupSignature(groupPackage.Categories));

                            foreach (var pair in fields)
                            {
                                var template = fieldSetter.Fields.FirstOrDefault(q => q.Key == pair.Key);
                                fieldSetter.SetFieldValue(template.Value.Id, pair.Value);
                            }

                            if (EnumHelper.GetValue <BulletinInstanceState>(dbBulletinInstance.State) != BulletinInstanceState.Publicated)
                            {
                                //Продолжить с пакетом «Обычная продажа»
                                var radioButton = WebWorker.WebDocument.GetElementsByTagName("input").Cast <HtmlElement>()
                                                  .FirstOrDefault(q => q.GetAttribute("id") == "pack1");
                                if (radioButton != null)
                                {
                                    radioButton.InvokeMember("click");
                                }


                                var buttons = WebWorker.WebDocument.GetElementsByTagName("button").Cast <HtmlElement>();
                                var pack    = "Продолжить без пакета";
                                var button  = buttons.FirstOrDefault(btn => btn.InnerText == pack);
                                if (button != null)
                                {
                                    button.InvokeMember("click");
                                }

                                Thread.Sleep(1000);
                            }
                            else
                            {
                                var button = WebWorker.WebDocument.GetElementsByTagName("button").Cast <HtmlElement>()
                                             .FirstOrDefault(q => q.GetAttribute("type") == "submit" && q.InnerText == "Продолжить");
                                if (button != null)
                                {
                                    button.InvokeMember("click");
                                }
                                Thread.Sleep(1000);
                            }
                        });
                    });
                }
            });
        }
Пример #7
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Генерирует xls для буллетинов. </summary>
        ///
        /// <remarks>   SV Milovanov, 05.02.2018. </remarks>
        ///-------------------------------------------------------------------------------------------------

        public override void GetXlsBulletins()
        {
            DCT.Execute(d =>
            {
                Exit();
                Auth();

                WebWorker.Execute(() =>
                {
                    DCT.Execute(data =>
                    {
                        var bulletins = data.Db1.BulletinInstances.Where(q => q.AccessId == data.Objects.CurrentAccess.Id).ToArray();

                        var groups = bulletins.Where(q => q.GroupId != Guid.Empty).GroupBy(q => q.GroupId);
                        foreach (var groupedBulletins in groups)
                        {
                            var dbGroup        = data.Db1.Groups.FirstOrDefault(q => q.Id == groupedBulletins.Key);
                            var groupContainer = GroupContainerList.Get(Uid);
                            var groupPackage   = groupContainer.GetGroupPackage(dbGroup.Hash);

                            var xls = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), $"edit_bulletins[{groupPackage}].xlsx"));
                            if (xls.Exists)
                            {
                                xls.Delete();
                            }

                            using (var package = new ExcelPackage(xls))
                            {
                                var worksheet = package.Workbook.Worksheets.Add("Мои объявления");
                                var pairs     = groupPackage.Fields;


                                var count = 0;
                                foreach (var pair in pairs)
                                {
                                    var cell = worksheet.Cells[1, count + 2];

                                    cell.Style.Font.Size = 14;
                                    cell.Value           = pair.Key;
                                    cell.AutoFitColumns();
                                    count++;
                                }
                                var row = 2;
                                foreach (var bulletin in groupedBulletins)
                                {
                                    var dbFields = data.Db1.BulletinFields.Where(q => q.BulletinInstanceId == bulletin.Id).ToArray();
                                    var column   = 0;
                                    foreach (var f in groupPackage.Fields)
                                    {
                                        var name          = f.Key;
                                        var fieldTemplate = data.Db1.FieldTemplates.FirstOrDefault(q => q.Name == name);
                                        var bulletinField = data.Db1.BulletinFields.FirstOrDefault(q => q.FieldId == fieldTemplate.Id && q.BulletinInstanceId == bulletin.Id);
                                        var cell          = worksheet.Cells[row, column + 2];

                                        var options = f.Value.Options;
                                        if (options != null && options.Length > 0)
                                        {
                                            var validation = worksheet.DataValidations.AddListValidation(cell.Address);
                                            validation.ShowErrorMessage = true;
                                            validation.ErrorStyle       = ExcelDataValidationWarningStyle.warning;
                                            validation.ErrorTitle       = "An invalid value was entered";
                                            validation.Error            = "Select a value from the list";
                                            for (var i = 0; i < options.Length; i++)
                                            {
                                                validation.Formula.Values.Add(options[i].Text);
                                            }
                                        }
                                        cell.Value = bulletinField.Value;
                                        column++;
                                    }

                                    worksheet.Column(1).Hidden = true;
                                    var urlCell   = worksheet.Cells[row, 1];
                                    urlCell.Value = bulletin.Id;

                                    row++;
                                }
                                package.Save();
                            }
                        }
                    });
                });
            });
        }
Пример #8
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Получаем список буллетинов учетки и сохраняем новые в БД </summary>
        ///
        /// <remarks>   SV Milovanov, 30.01.2018. </remarks>
        ///-------------------------------------------------------------------------------------------------

        public override void GetBulletins()
        {
            DCT.Execute(data =>
            {
                Exit();
                Auth();
                var context   = DCT.Context;
                var bulletins = new List <BulletinPackage>();
                var tabStates = new List <TabState>();
                WebWorker.Execute(() =>
                {
                    WebWorker.NavigatePage(ProfileUrl);

                    var tabs = WebWorker.WebDocument.GetElementsByTagName("li").Cast <HtmlElement>()
                               .Where(q => q.GetAttribute("className").Contains("tabs-item")).ToArray();

                    tabStates.Add(new TabState
                    {
                        Title = "Активные",
                        Href  = ProfileUrl,
                    });

                    foreach (var tab in tabs)
                    {
                        if (!tab.CanHaveChildren)
                        {
                            continue;
                        }

                        foreach (HtmlElement ch in tab.Children)
                        {
                            if (ch.TagName.ToLower() == "a")
                            {
                                var tabUrl   = ch.GetAttribute("href");
                                var tabState = ch.InnerText;

                                tabStates.Add(new TabState
                                {
                                    Title = tabState,
                                    Href  = tabUrl,
                                });
                            }
                        }
                    }
                });
                WebWorker.Execute(() =>
                {
                    foreach (var tabState in tabStates)
                    {
                        WebWorker.NavigatePage(tabState.Href);

                        var nextPages = new List <string>
                        {
                            tabState.Href
                        };

                        var hasNextPage = true;
                        do
                        {
                            var result = GetBulletinPages(tabState.Title);
                            bulletins.AddRange(result);

                            var nextPage = WebWorker.WebDocument.GetElementsByTagName("a").Cast <HtmlElement>()
                                           .FirstOrDefault(q => q.GetAttribute("className").Contains("js-pagination-next"));
                            if (nextPage == null)
                            {
                                hasNextPage = false;
                            }
                            else
                            {
                                var nextPageHref = nextPage.GetAttribute("href");
                                nextPages.Add(nextPageHref);
                                hasNextPage = true;
                                nextPage.InvokeMember("click");
                                Thread.Sleep(1000);
                            }
                        } while (hasNextPage);
                    }
                });

                WebWorker.Execute(() =>
                {
                    var groupContainer = GroupContainerList.Get(Uid);
                    foreach (var bulletin in bulletins)
                    {
                        var url = Path.Combine(bulletin.Url, "edit");
                        WebWorker.NavigatePage(url);
                        Thread.Sleep(1500);

                        var groupElement = WebWorker.WebDocument.GetElementsByTagName("div").Cast <HtmlElement>()
                                           .FirstOrDefault(q => q.GetAttribute("className").Contains("form-category-path"));

                        if (groupElement == null)
                        {
                            continue;
                        }

                        var categories     = groupElement.InnerText.Split('/').Select(q => q.Trim()).ToArray();
                        bulletin.Signature = new GroupSignature(categories);

                        var fieldSetter = FieldContainerList.Get(Uid);
                        fieldSetter.LoadFieldsFromGroup(bulletin.Signature);

                        var dictionary = new Dictionary <string, string>();
                        foreach (var field in fieldSetter.Fields)
                        {
                            var value = fieldSetter.GetFieldValue(field.Value.Id);
                            dictionary.Add(field.Key, value);
                        }
                        bulletin.Fields = dictionary;
                    }
                });

                WebWorker.Execute(() =>
                {
                    DCT.Execute(d =>
                    {
                        foreach (var bulletin in bulletins)
                        {
                            var url = bulletin.Url;
                            var bs  = d.Db1.BulletinInstances.ToArray();
                            var dbBulletinInstance = d.Db1.BulletinInstances.FirstOrDefault(q => q.Url == url);
                            if (dbBulletinInstance == null)
                            {
                                var dbBulletin = new Bulletin
                                {
                                    UserId = d.Objects.CurrentUser.Id,
                                };
                                d.Db1.Bulletins.Add(dbBulletin);
                                d.Db1.SaveChanges();

                                var groupId = Guid.Empty;
                                if (bulletin.Signature != null)
                                {
                                    var groupHash = bulletin.Signature.GetHash();

                                    var dbGroup = d.Db1.Groups.FirstOrDefault(q => q.Hash == groupHash);
                                    groupId     = dbGroup.Id;
                                }

                                dbBulletinInstance = new BulletinInstance
                                {
                                    GroupId      = groupId,
                                    AccessId     = d.Objects.CurrentAccess.Id,
                                    BoardId      = Uid,
                                    BulletinId   = dbBulletin.Id,
                                    HasRemoved   = false,
                                    LastChangeId = null,
                                    Url          = bulletin.Url,
                                    State        = 0,
                                };
                                d.Db1.BulletinInstances.Add(dbBulletinInstance);
                                d.Db1.SaveChanges();

                                if (bulletin.Fields == null)
                                {
                                    continue;
                                }

                                foreach (var field in bulletin.Fields)
                                {
                                    var dbFieldTemplate = d.Db1.FieldTemplates.FirstOrDefault(q => q.Name == field.Key);
                                    if (dbFieldTemplate != null)
                                    {
                                        var dbBulletinField = d.Db1.BulletinFields.FirstOrDefault(q => q.BulletinInstanceId == dbBulletinInstance.Id && q.FieldId == dbFieldTemplate.Id);
                                        if (dbBulletinField == null)
                                        {
                                            dbBulletinField = new BulletinField
                                            {
                                                BulletinInstanceId = dbBulletinInstance.Id,
                                                FieldId            = dbFieldTemplate.Id,
                                                Value = field.Value,
                                            };
                                            d.Db1.BulletinFields.Add(dbBulletinField);
                                            d.Db1.SaveChanges();
                                        }
                                    }
                                }
                            }
                        }
                    });
                });
                //WebWorker.Execute(() =>
                //{
                //    var groupContainer = GroupContainerList.Get(Uid);
                //    foreach (var bulletin in bulletins)
                //    {
                //        var url = Path.Combine(bulletin.Url, "edit");
                //        WebWorker.NavigatePage(url);
                //        Thread.Sleep(1500);

                //        var groupElement = WebWorker.WebDocument.GetElementsByTagName("div").Cast<HtmlElement>()
                //            .FirstOrDefault(q => q.GetAttribute("className").Contains("form-category-path"));

                //        if (groupElement == null) continue;

                //        var categories = groupElement.InnerText.Split('/').Select(q => q.Trim()).ToArray();
                //        bulletin.Signature = new GroupSignature(categories);

                //        var group = groupContainer.Get(bulletin.Signature.GetHash());

                //        if (group == null) continue;

                //        var fieldSetter = FieldContainerList.Get(Uid);
                //        fieldSetter.LoadFieldsFromGroup(bulletin.Signature);

                //        var dictionary = new Dictionary<string, string>();
                //        foreach (var field in group.Fields)
                //        {
                //            var value = fieldSetter.GetField(field.Key);
                //            dictionary.Add(field.Key, value);
                //        }
                //        bulletin.Fields = dictionary;
                //    }


                //});

                //WebWorker.Execute(() =>
                //{
                //    var groups = bulletins.Where(q => q.Fields != null && q.Fields.Count > 0).GroupBy(q => q.Signature.ToString());
                //    foreach (var groupedBulletins in groups)
                //    {
                //        var xls = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), $"edit_bulletins[{groupedBulletins.Key}].xlsx"));
                //        if (xls.Exists)
                //            xls.Delete();
                //        var firstBulletin = groupedBulletins.FirstOrDefault();
                //        using (var package = new ExcelPackage(xls))
                //        {
                //            var worksheet = package.Workbook.Worksheets.Add("Мои объявления");
                //            var keys = firstBulletin.Fields.Keys;
                //            var count = 0;
                //            foreach (var k in keys)
                //            {
                //                var cell = worksheet.Cells[1, count + 1];
                //                cell.Style.Font.Size = 14;
                //                cell.Value = k;
                //                cell.AutoFitColumns();
                //                count++;
                //            }
                //            var row = 2;
                //            foreach (var bulletin in groupedBulletins)
                //            {
                //                var column = 0;
                //                foreach (var k in keys)
                //                {
                //                    var cell = worksheet.Cells[row, column + 1];
                //                    var field = bulletin.Fields[k];
                //                    cell.Value = field;
                //                    column++;
                //                }

                //                worksheet.Column(column + 1).Hidden = true;
                //                var urlCell = worksheet.Cells[row, column + 1];
                //                urlCell.Value = bulletin.Url;

                //                worksheet.Column(column + 2).Hidden = true;
                //                var stateCell = worksheet.Cells[row, column + 2];
                //                stateCell.Value = bulletin.State;
                //                row++;
                //            }

                //            package.Save();
                //        }

                //    }
                //});
            });
        }
Пример #9
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Gets the bulletins. </summary>
        ///
        /// <remarks>   SV Milovanov, 30.01.2018. </remarks>
        ///-------------------------------------------------------------------------------------------------

        public override void GetBulletins()
        {
            _DCT.Execute(data =>
            {
                Exit();
                Auth();

                var bulletins = new List <Bulletin>();
                var tabStates = new List <TabState>();
                WebWorker.Execute(() =>
                {
                    WebWorker.NavigatePage(ProfileUrl);

                    var tabs = WebWorker.WebDocument.GetElementsByTagName("li").Cast <HtmlElement>()
                               .Where(q => q.GetAttribute("className").Contains("tabs-item")).ToArray();

                    tabStates.Add(new TabState
                    {
                        Title = "Активные",
                        Href  = ProfileUrl,
                    });

                    foreach (var tab in tabs)
                    {
                        if (!tab.CanHaveChildren)
                        {
                            continue;
                        }

                        foreach (HtmlElement ch in tab.Children)
                        {
                            if (ch.TagName.ToLower() == "a")
                            {
                                var tabUrl   = ch.GetAttribute("href");
                                var tabState = ch.InnerText;

                                tabStates.Add(new TabState
                                {
                                    Title = tabState,
                                    Href  = tabUrl,
                                });
                            }
                        }
                    }
                });
                WebWorker.Execute(() =>
                {
                    foreach (var tabState in tabStates)
                    {
                        WebWorker.NavigatePage(tabState.Href);

                        var nextPages = new List <string>();
                        nextPages.Add(tabState.Href);

                        var hasNextPage = true;
                        do
                        {
                            var result = GetBulletinPages(tabState.Title);
                            bulletins.AddRange(result);

                            var nextPage = WebWorker.WebDocument.GetElementsByTagName("a").Cast <HtmlElement>()
                                           .FirstOrDefault(q => q.GetAttribute("className").Contains("js-pagination-next"));
                            if (nextPage == null)
                            {
                                hasNextPage = false;
                            }
                            else
                            {
                                var nextPageHref = nextPage.GetAttribute("href");
                                nextPages.Add(nextPageHref);
                                hasNextPage = true;
                                nextPage.InvokeMember("click");
                                Thread.Sleep(1000);
                            }
                        } while (hasNextPage);
                    }

                    bulletins = bulletins;
                });

                WebWorker.Execute(() =>
                {
                    var groupContainer = GroupContainerList.Get(null);
                    foreach (var bulletin in bulletins)
                    {
                        var url = Path.Combine(bulletin.Url, "edit");
                        WebWorker.NavigatePage(url);
                        Thread.Sleep(1500);

                        var groupElement = WebWorker.WebDocument.GetElementsByTagName("div").Cast <HtmlElement>()
                                           .FirstOrDefault(q => q.GetAttribute("className").Contains("form-category-path"));

                        if (groupElement == null)
                        {
                            continue;
                        }

                        var categories     = groupElement.InnerText.Split('/').Select(q => q.Trim()).ToArray();
                        bulletin.Signature = new GroupSignature(categories);

                        var group = groupContainer.Get(bulletin.Signature.GetHash());

                        if (group == null)
                        {
                            continue;
                        }

                        var fieldSetter = FieldSetterContainerList.Get(Uid);
                        fieldSetter.LoadFieldsFromGroup(bulletin.Signature);

                        var dictionary = new Dictionary <string, string>();
                        foreach (var field in group.Fields)
                        {
                            var value = fieldSetter.GetField(field.Key);
                            dictionary.Add(field.Key, value);
                        }
                        bulletin.Fields = dictionary;
                    }
                });

                WebWorker.Execute(() =>
                {
                    var groups = bulletins.Where(q => q.Fields != null && q.Fields.Count > 0).GroupBy(q => q.Signature.ToString());
                    foreach (var groupedBulletins in groups)
                    {
                        var xls = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), $"edit_bulletins[{groupedBulletins.Key}].xlsx"));
                        if (xls.Exists)
                        {
                            xls.Delete();
                        }
                        var firstBulletin = groupedBulletins.FirstOrDefault();
                        using (var package = new ExcelPackage(xls))
                        {
                            var worksheet = package.Workbook.Worksheets.Add("Мои объявления");
                            var keys      = firstBulletin.Fields.Keys;
                            var count     = 0;
                            foreach (var k in keys)
                            {
                                var cell             = worksheet.Cells[1, count + 1];
                                cell.Style.Font.Size = 14;
                                cell.Value           = k;
                                cell.AutoFitColumns();
                                count++;
                            }
                            var row = 2;
                            foreach (var bulletin in groupedBulletins)
                            {
                                var column = 0;
                                foreach (var k in keys)
                                {
                                    var cell   = worksheet.Cells[row, column + 1];
                                    var field  = bulletin.Fields[k];
                                    cell.Value = field;
                                    column++;
                                }

                                worksheet.Column(column + 1).Hidden = true;
                                var urlCell   = worksheet.Cells[row, column + 1];
                                urlCell.Value = bulletin.Url;

                                worksheet.Column(column + 2).Hidden = true;
                                var stateCell   = worksheet.Cells[row, column + 2];
                                stateCell.Value = bulletin.State;
                                row++;
                            }

                            package.Save();
                        }
                    }
                });
            });
        }